您的位置:首页 > 编程语言 > Qt开发

使用Qt调用openssl 从内存中读取私钥对RSA密文进行解密

2017-12-12 00:43 537 查看
头文件

#ifndef CTOOLS_H
#define CTOOLS_H

#include <windows.h>
#include <QString>
#include "openssl/rsa.h"
#include "openssl/pem.h"
#include <QDebug>
#include "lusb0_usb.h"
#include <QFile>
#include <QByteArray>
#include <QLibrary>

class CTools
{
public:
CTools();
~CTools();
BOOL GetBoardSerialNum(QString *boardSerialNum);//获取主板序列号
void GenPriKeyDataFromFile(QString priKeyPath , QString priKeyDataOutputPath);
QString Encrypt(QString input);//加密
QString Decrypt(QByteArray encryptContent);//解密
void USBtest();
};

#endif // CTOOLS_H

源文件
#include "ctools.h"
extern "C"
{
#include "openssl/applink.c"
}
using namespace std;
CTools::CTools()
{

}

CTools::~CTools(){

}

//解密私钥数据
const unsigned char privateKey[] = {
0x2d,0x2d,0x2d,0x2d,0x2d,0x42,0x45,0x47,0x49,0x4e,0x20,0x52,0x53,0x41,0x20,0x50,0x52,0x49,0x56,0x41,
0x54,0x45,0x20,0x4b,0x45,0x59,0x2d,0x2d,0x2d,0x2d,0x2d,0xa,0x4d,0x49,0x49,0x43,0x58,0x41,0x49,0x42,
0x41,0x41,0x4b,0x42,0x67,0x51,0x43,0x6b,0x78,0x61,0x41,0x53,0x55,0x56,0x6c,0x31,0x6c,0x55,0x79,0x75,
0x75,0x67,0x6c,0x42,0x52,0x72,0x5a,0x57,0x70,0x6a,0x56,0x78,0x6c,0x37,0x58,0x2b,0x38,0x36,0x6a,0x68,
0x6d,0x46,0x46,0x38,0x59,0x42,0x2b,0x47,0x64,0x5a,0x6f,0x50,0x59,0x42,0x32,0x73,0xa,0x6a,0x75,0x6c,
0x5a,0x75,0x31,0x31,0x39,0x30,0x57,0x34,0x76,0x61,0x78,0x4b,0x44,0x6e,0x67,0x4a,0x68,0x34,0x46,0x50,
0x64,0x64,0x4c,0x6f,0x61,0x4a,0x44,0x46,0x54,0x4e,0x41,0x56,0x6a,0x65,0x49,0x6e,0x59,0x6e,0x5a,0x47,
0x35,0x56,0x62,0x72,0x45,0x34,0x55,0x6a,0x54,0x71,0x62,0x50,0x5a,0x31,0x70,0x37,0x63,0x2b,0x79,0x74,
0x7a,0xa,0x6c,0x63,0x2f,0x79,0x72,0x6a,0x54,0x64,0x59,0x37,0x70,0x62,0x30,0x43,0x73,0x47,0x5a,0x75,
0x77,0x41,0x4e,0x50,0x77,0x79,0x33,0x36,0x57,0x43,0x64,0x4b,0x4f,0x38,0x37,0x6d,0x67,0x43,0x34,0x6d,
0x30,0x34,0x59,0x50,0x77,0x76,0x67,0x41,0x51,0x50,0x39,0x39,0x4b,0x31,0x79,0x74,0x42,0x6d,0x47,0x77,
0x49,0x44,0x41,0x51,0x41,0x42,0xa,0x41,0x6f,0x47,0x41,0x45,0x68,0x54,0x39,0x39,0x41,0x53,0x70,0x5a,
0x4a,0x58,0x31,0x7a,0x46,0x62,0x75,0x48,0x52,0x4f,0x39,0x66,0x74,0x54,0x4f,0x6d,0x4b,0x43,0x6c,0x67,
0x45,0x30,0x4e,0x41,0x33,0x54,0x4c,0x76,0x48,0x4a,0x77,0x41,0x7a,0x6c,0x30,0x70,0x71,0x74,0x4e,0x6c,
0x6c,0x6f,0x34,0x6b,0x58,0x68,0x57,0x55,0x6a,0x42,0x68,0xa,0x66,0x79,0x4b,0x6f,0x37,0x58,0x69,0x78,
0x6d,0x6a,0x77,0x62,0x39,0x2f,0x6d,0x50,0x55,0x72,0x38,0x57,0x43,0x71,0x4e,0x79,0x30,0x38,0x4b,0x57,
0x39,0x57,0x6f,0x6c,0x68,0x4d,0x6c,0x38,0x75,0x34,0x38,0x45,0x2f,0x33,0x65,0x78,0x38,0x56,0x51,0x6f,
0x37,0x41,0x62,0x51,0x43,0x64,0x43,0x56,0x63,0x6b,0x79,0x38,0x49,0x4b,0x4a,0x67,0xa,0x52,0x76,0x4a,
0x43,0x69,0x2f,0x35,0x59,0x44,0x4a,0x6c,0x70,0x37,0x38,0x32,0x51,0x68,0x69,0x6f,0x43,0x30,0x5a,0x44,
0x45,0x37,0x49,0x6a,0x68,0x54,0x45,0x45,0x43,0x6f,0x72,0x67,0x6a,0x79,0x38,0x4c,0x48,0x4e,0x53,0x47,
0x62,0x62,0x73,0x45,0x43,0x51,0x51,0x44,0x53,0x74,0x43,0x39,0x36,0x58,0x65,0x63,0x52,0x73,0x72,0x36,
0x47,0xa,0x46,0x63,0x53,0x47,0x6e,0x62,0x67,0x6f,0x37,0x49,0x4a,0x4a,0x31,0x74,0x2f,0x58,0x2b,0x56,
0x61,0x44,0x65,0x49,0x5a,0x6c,0x75,0x79,0x34,0x62,0x59,0x64,0x33,0x4e,0x55,0x72,0x70,0x76,0x4e,0x5a,
0x54,0x35,0x6a,0x6a,0x64,0x62,0x68,0x49,0x35,0x75,0x31,0x7a,0x51,0x39,0x46,0x47,0x53,0x55,0x35,0x69,
0x53,0x42,0x70,0x34,0x67,0x64,0xa,0x71,0x2b,0x65,0x77,0x57,0x74,0x45,0x4e,0x41,0x6b,0x45,0x41,0x79,
0x44,0x47,0x6a,0x5a,0x79,0x66,0x6d,0x50,0x41,0x45,0x43,0x7a,0x6a,0x6b,0x58,0x7a,0x43,0x38,0x6e,0x63,
0x50,0x5a,0x6e,0x7a,0x52,0x65,0x64,0x72,0x36,0x42,0x6e,0x48,0x36,0x2b,0x65,0x68,0x54,0x6e,0x4b,0x7a,
0x63,0x71,0x6c,0x41,0x6a,0x38,0x75,0x38,0x49,0x72,0x47,0xa,0x45,0x56,0x7a,0x74,0x55,0x6c,0x4c,0x68,
0x66,0x44,0x50,0x4a,0x55,0x45,0x66,0x58,0x2f,0x49,0x6a,0x30,0x48,0x53,0x73,0x67,0x30,0x63,0x6d,0x78,
0x42,0x31,0x77,0x35,0x78,0x77,0x4a,0x41,0x4f,0x58,0x70,0x35,0x38,0x54,0x47,0x6f,0x6c,0x55,0x56,0x6a,
0x67,0x41,0x52,0x30,0x4a,0x68,0x7a,0x6b,0x58,0x68,0x57,0x57,0x76,0x54,0x6e,0x6d,0xa,0x75,0x6d,0x34,
0x45,0x55,0x62,0x30,0x52,0x50,0x4c,0x4e,0x42,0x4d,0x71,0x73,0x52,0x37,0x4b,0x38,0x43,0x75,0x4d,0x2b,
0x76,0x49,0x68,0x7a,0x50,0x73,0x53,0x47,0x4b,0x45,0x57,0x61,0x58,0x6b,0x34,0x6e,0x36,0x6e,0x6a,0x76,
0x68,0x2f,0x5a,0x53,0x4d,0x4a,0x7a,0x76,0x37,0x36,0x6a,0x6e,0x38,0x43,0x51,0x4a,0x41,0x48,0x4f,0x38,
0x50,0xa,0x72,0x74,0x6b,0x56,0x62,0x5a,0x61,0x33,0x30,0x52,0x5a,0x76,0x57,0x68,0x4e,0x32,0x6e,0x39,
0x7a,0x39,0x49,0x36,0x64,0x47,0x49,0x78,0x77,0x4c,0x79,0x34,0x69,0x57,0x59,0x4b,0x72,0x35,0x70,0x4d,
0x53,0x6c,0x46,0x4b,0x34,0x4e,0x47,0x72,0x62,0x7a,0x36,0x59,0x36,0x45,0x76,0x6d,0x45,0x38,0x4e,0x62,
0x64,0x47,0x59,0x56,0x51,0x41,0xa,0x34,0x33,0x37,0x6e,0x79,0x55,0x39,0x79,0x62,0x74,0x2b,0x33,0x74,
0x6c,0x69,0x65,0x41,0x51,0x4a,0x42,0x41,0x4a,0x4b,0x71,0x54,0x2f,0x77,0x73,0x66,0x67,0x32,0x41,0x36,
0x53,0x61,0x4d,0x54,0x2b,0x4d,0x48,0x6c,0x2b,0x68,0x71,0x44,0x4d,0x33,0x71,0x67,0x65,0x5a,0x39,0x76,
0x4b,0x70,0x77,0x6d,0x4e,0x72,0x64,0x71,0x78,0x68,0x76,0xa,0x32,0x6e,0x6e,0x67,0x62,0x52,0x79,0x67,
0x6b,0x51,0x72,0x67,0x76,0x6c,0x4e,0x31,0x6c,0x2f,0x6f,0x71,0x66,0x59,0x6e,0x5a,0x4e,0x72,0x7a,0x4d,
0x76,0x72,0x62,0x55,0x70,0x53,0x4f,0x7a,0x33,0x70,0x67,0x48,0x4c,0x63,0x6b,0x3d,0xa,0x2d,0x2d,0x2d,
0x2d,0x2d,0x45,0x4e,0x44,0x20,0x52,0x53,0x41,0x20,0x50,0x52,0x49,0x56,0x41,0x54,0x45,0x20,0x4b,0x45,
0x59,0x2d,0x2d,0x2d,0x2d,0x2d,0xa,
};

BOOL CTools::GetBoardSerialNum(QString *boardSerialNum){
const long MAX_COMMAND_SIZE = 10000; // 命令行输出缓冲大小
WCHAR szFetCmd[] = L"wmic BaseBoard get SerialNumber"; // 获取主板序列号命令行
string strEnSearch = "SerialNumber"; // 主板序列号的前导信息

BOOL bret = FALSE;
HANDLE hReadPipe = NULL; //读取管道
HANDLE hWritePipe = NULL; //写入管道
PROCESS_INFORMATION pi; //进程信息
STARTUPINFO si; //控制命令行窗口信息
SECURITY_ATTRIBUTES sa; //安全属性

char szBuffer[MAX_COMMAND_SIZE+1] = {0}; // 放置命令行结果的输出缓冲区
string strBuffer;
unsigned long count = 0;
long ipos = 0;

memset(&pi, 0, sizeof(pi));
memset(&si, 0, sizeof(si));
memset(&sa, 0, sizeof(sa));

pi.hProcess = NULL;
pi.hThread = NULL;
si.cb = sizeof(STARTUPINFO);
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;

//1.0 创建管道
bret = CreatePipe(&hReadPipe, &hWritePipe, &sa, 0);
if(!bret)
{
goto END;
}

//2.0 设置命令行窗口的信息为指定的读写管道
GetStartupInfo(&si);
si.hStdError = hWritePipe;
si.hStdOutput = hWritePipe;
si.wShowWindow = SW_HIDE; //隐藏命令行窗口
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;

//3.0 创建获取命令行的进程
bret = CreateProcess(NULL, szFetCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi );
if(!bret)
{
goto END;
}

//4.0 读取返回的数据
WaitForSingleObject (pi.hProcess, 500/*INFINITE*/);
bret = ReadFile(hReadPipe, szBuffer, MAX_COMMAND_SIZE, &count, 0);
if(!bret)
{
goto END;
}

//5.0 查找主板序列号
bret = FALSE;
strBuffer = szBuffer;
ipos = strBuffer.find(strEnSearch);

if (ipos < 0) // 没有找到
{
goto END;
}
else
{
strBuffer = strBuffer.substr(ipos+strEnSearch.length());
}

memset(szBuffer, 0x00, sizeof(szBuffer));
strcpy_s(szBuffer, strBuffer.c_str());

//去掉中间的空格 \r \n
int j = 0;
for (int i = 0; i < strlen(szBuffer); i++)
{
if (szBuffer[i] != ' ' && szBuffer[i] != '\n' && szBuffer[i] != '\r')
{
*boardSerialNum += szBuffer[i];
j++;
}
}

bret = TRUE;

END:
//关闭所有的句柄
CloseHandle(hWritePipe);
CloseHandle(hReadPipe);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

return(bret);
}

void CTools::GenPriKeyDataFromFile(QString priKeyPath , QString priKeyDataOutputPath){
QFile *file = new QFile(priKeyPath);//解密私钥
file->open(QIODevice::ReadOnly);
QByteArray privateKey = file->readAll();
file->close();
delete file;
file = new QFile(priKeyDataOutputPath);
file->open(QIODevice::ReadWrite);
char str_data[10] = {0};
file->write("const unsigned char privateKey[] = {\n");
for(int i = 0 ; i < privateKey.length() ; ++i){
sprintf(str_data , "0x%x," , (int)privateKey.at(i));
file->write(str_data);
if((i+1)%20 == 0){
file->write("\n");
}
}
file->write("\n};\n");
file->close();
delete file;
}

QString CTools::Decrypt(QByteArray encryptContent){
QString str_ret = "";
RSA *rsa = NULL;
int rsa_len = 0;
char *de = NULL;
BIO *bufio = NULL;
bufio = BIO_new_mem_buf((void*)privateKey , sizeof(privateKey));
if(NULL == bufio){
qDebug()<<"分配BIO空间失败";
return str_ret;
}

if (NULL == PEM_read_bio_RSAPrivateKey(bufio ,&rsa , 0 , NULL)){
qDebug()<<("获取私钥失败\n");
BIO_free(bufio);
return str_ret;
}

rsa_len = RSA_size(rsa);
de = (char *)malloc(rsa_len + 1);
if(NULL == de){
qDebug()<<("分配空间失败\n");
BIO_free(bufio);
return str_ret;
}
memset(de, 0, rsa_len + 1);
//注意下面的红色部分,这里必须是使用这个,之前网上很多资料使用的是RSA_NO_PADDING,结果无论如何怎么也不能正确解密
if(0 > RSA_private_decrypt(encryptContent.length(), (unsigned char *)encryptContent.data(), (unsigned char*)de, rsa, RSA_PKCS1_PADDING)){
qDebug()<<"解密失败";
BIO_free(bufio);
free(de);
return str_ret;
}
str_ret.prepend(de);

BIO_free(bufio);
free(de);

return str_ret;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: