使用Qt調用openssl 從內存中讀取私鑰對RSA密文進行解密

頭文件

#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;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章