Qt 操作openssl进行RSA加密解密 PEM_read_bio_RSAPrivateKey 返回NULL

这个根据操作没啥难的,说说我踩的坑.

1 生成的秘钥的格式是固定的,一定注意换行符 \n 不能省略.我曾经使用QLineEdit 输入秘钥,结果就是程序走到   PEM_read_bio_RSAPrivateKey  总是返回 NULL  

  解决方法 输入秘钥时候,使用 QPlainEdit 替换 QLineEdit   因为 QPlainEdit 能保留 \n QLineEdit在输入时候,默认将 \n 替换为空格,空格输入加密解密程序就会报错

2 在电脑上进行加密解密一般生成的都是客打印字符,但是如果是使用单片机生成的加密数据,那可就不一定是客打印数据了,此时不用担心,因为openssl的解密是支持hex输入的.

3 此处我使用的rsa加密解密是参考别人的,稍作修改,注意网上还有一个说法是必须是 win32 的程序

 

 

pro 引入如下

INCLUDEPATH += $$PWD/openssl/
win32 {
    LIBS += -lwsock32
    LIBS += -L$$PWD/lib/ -llibeay32 -lssleay32
}

 

文件目录如下

 

 

 

rsa.h

复制代码
#ifndef RSA_H
#define RSA_H

#include <QString>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>

#define BEGIN_RSA_PUBLIC_KEY  "BEGIN RSA PUBLIC KEY"
#define BEGIN_RSA_PRIVATE_KEY  "BEGIN RSA PRIVATE KEY"
#define BEGIN_PUBLIC_KEY      "BEGIN PUBLIC KEY"
#define BEGIN_PRIVATE_KEY      "BEGIN PRIVATE KEY"
#define KEY_LENGTH            1024

class rsa
{
public:
    rsa();
    ~rsa();

    bool createRSAKey(QString &strPubKey, QString &strPriKey);

    QString rsaPriEncrypt(const QString &strPlainData, const QString &strPriKey);

    QString rsaPubDecrypt(const QString &strDecryptData, const QString &strPubKey);

    QString rsaPubEncrypt(const QString &strPlainData, const QString &strPubKey);

    QString rsaPriDecrypt(const QString &strDecryptData, const QString &strPriKey);
    QString rsaPriDecryptHex(const QString &strDecryptData, const QString &strPriKey);

};

#endif // RSA_H
复制代码

 

rsa.cpp

复制代码
#include <QDebug>
#include "rsa.h"

#define myDebugMsg(msg) qDebug()<<QString("[Debug] File:%1     Line:%2     Function:%3     Msg:%4").arg(__FILE__).arg(__LINE__).arg(__FUNCTION__).arg(msg)
#define myDebug qDebug()<<QString("[Debug] File:%1     Line:%2     Function:%3").arg(__FILE__).arg(__LINE__).arg(__FUNCTION__)


rsa::rsa()
{

}

rsa::~rsa()
{

}

bool rsa::createRSAKey(QString &strPubKey, QString &strPriKey)
{
    RSA *pRsa = RSA_generate_key(KEY_LENGTH, RSA_3, NULL, NULL);
    if (!pRsa){
        return false;
    }

    BIO *pPriBio = BIO_new(BIO_s_mem());
    PEM_write_bio_RSAPrivateKey(pPriBio, pRsa, NULL, NULL, 0, NULL, NULL);
    BIO *pPubBio = BIO_new(BIO_s_mem());
    PEM_write_bio_RSAPublicKey(pPubBio, pRsa);

    //获取长度
    size_t nPriKeyLen = BIO_pending(pPriBio);
    size_t nPubKeyLen = BIO_pending(pPubBio);

    //密钥对读取到字符串
    char* pPriKey = new char[nPriKeyLen];
    char* pPubKey = new char[nPubKeyLen];
    BIO_read(pPriBio, pPriKey, nPriKeyLen);
    BIO_read(pPubBio, pPubKey, nPubKeyLen);

    //存储密钥对
    strPubKey = QByteArray(pPubKey, nPubKeyLen);
    strPriKey = QByteArray(pPriKey, nPriKeyLen);

    //内存释放
    RSA_free(pRsa);
    BIO_free_all(pPriBio);
    BIO_free_all(pPubBio);
    delete pPriKey;
    delete pPubKey;

    return true;
}

QString rsa::rsaPriEncrypt(const QString &strPlainData, const QString &strPriKey)
{
    QByteArray priKeyArry = strPriKey.toUtf8();
    uchar* pPriKey = (uchar*)priKeyArry.data();
    BIO* pKeyBio = BIO_new_mem_buf(pPriKey, strPriKey.length());
    if (pKeyBio == NULL) {
        return "";
    }

    RSA* pRsa = RSA_new();
    pRsa = PEM_read_bio_RSAPrivateKey(pKeyBio, &pRsa, NULL, NULL);

//    if (strPriKey.contains(BEGIN_RSA_PRIVATE_KEY)) {
//        pRsa = PEM_read_bio_RSAPrivateKey(pKeyBio, &pRsa, NULL, NULL);
//    }
//    else {
//        pRsa = PEM_read_bio_RSA_PRIVATE(pKeyBio, &pRsa, NULL, NULL);
//    }

    if (pRsa == NULL) {
        BIO_free_all(pKeyBio);
        return "";
    }

    int nLen = RSA_size(pRsa);
    char* pEncryptBuf = new char[nLen];
    memset(pEncryptBuf, 0, nLen);

    //加密
    QByteArray plainDataArry = strPlainData.toUtf8();
    int nPlainDataLen = plainDataArry.length();
    uchar* pPlainData = (uchar*)plainDataArry.data();
    int nSize = RSA_private_encrypt(nPlainDataLen,
                                    pPlainData,
                                    (uchar*)pEncryptBuf,
                                    pRsa,
                                    RSA_PKCS1_PADDING);

    QString strEncryptData = "";
    if (nSize >= 0) {
        QByteArray arry(pEncryptBuf, nSize);
        strEncryptData = arry.toBase64();
    }

    //释放内存
    delete pEncryptBuf;
    BIO_free_all(pKeyBio);
    RSA_free(pRsa);

    return strEncryptData;
}

QString rsa::rsaPubDecrypt(const QString &strDecryptData, const QString &strPubKey)
{
    QByteArray pubKeyArry = strPubKey.toUtf8();
    uchar* pPubKey = (uchar*)pubKeyArry.data();
    BIO* pKeyBio = BIO_new_mem_buf(pPubKey, strPubKey.length());
    if (pKeyBio == NULL) {
        return "";
    }

    RSA* pRsa = RSA_new();
    if (strPubKey.contains(BEGIN_RSA_PUBLIC_KEY)) {
        pRsa = PEM_read_bio_RSAPublicKey(pKeyBio, &pRsa, NULL, NULL);

    }
    else {
        pRsa = PEM_read_bio_RSA_PUBKEY(pKeyBio, &pRsa, NULL, NULL);

    }

    if (pRsa == NULL) {
        BIO_free_all(pKeyBio);
        return "";
    }

    int nLen = RSA_size(pRsa);
    char* pPlainBuf = new char[nLen];
    memset(pPlainBuf, 0, nLen);

    //解密
    QByteArray decryptDataArry = strDecryptData.toUtf8();
    decryptDataArry = QByteArray::fromBase64(decryptDataArry);
    int nDecryptDataLen = decryptDataArry.length();
    uchar* pDecryptData = (uchar*)decryptDataArry.data();
    int nSize = RSA_public_decrypt(nDecryptDataLen,
                                   pDecryptData,
                                   (uchar*)pPlainBuf,
                                   pRsa,
                                   RSA_PKCS1_PADDING);

    QString strPlainData = "";
    if (nSize >= 0) {
        strPlainData = QByteArray(pPlainBuf, nSize);
    }

    //释放内存
    delete pPlainBuf;
    BIO_free_all(pKeyBio);
    RSA_free(pRsa);

    return strPlainData;
}

QString rsa::rsaPubEncrypt(const QString &strPlainData, const QString &strPubKey)
{
    QByteArray pubKeyArry = strPubKey.toUtf8();
    uchar* pPubKey = (uchar*)pubKeyArry.data();
    BIO* pKeyBio = BIO_new_mem_buf(pPubKey, pubKeyArry.length());
    if (pKeyBio == NULL) {
        return "";
    }


    RSA* pRsa = RSA_new();
    if (strPubKey.contains(BEGIN_RSA_PUBLIC_KEY)) {
        pRsa = PEM_read_bio_RSAPublicKey(pKeyBio, &pRsa, NULL, NULL);

    }
    else {
        pRsa = PEM_read_bio_RSA_PUBKEY(pKeyBio, &pRsa, NULL, NULL);

    }


    if (pRsa == NULL) {
        BIO_free_all(pKeyBio);
        return "";
    }

    int nLen = RSA_size(pRsa);
    char* pEncryptBuf = new char[nLen];
    memset(pEncryptBuf, 0, nLen);

    //加密
    QByteArray plainDataArry = strPlainData.toUtf8();
    int nPlainDataLen = plainDataArry.length();
    uchar* pPlainData = (uchar*)plainDataArry.data();
    int nSize = RSA_public_encrypt(nPlainDataLen,
                                   pPlainData,
                                   (uchar*)pEncryptBuf,
                                   pRsa,
                                   RSA_PKCS1_PADDING);

    QString strEncryptData = "";
    if (nSize >= 0) {
        QByteArray arry(pEncryptBuf, nSize);
        strEncryptData = arry.toBase64();
    }

    //释放内存
    delete pEncryptBuf;
    BIO_free_all(pKeyBio);
    RSA_free(pRsa);

    return strEncryptData;
}

QString rsa::rsaPriDecrypt(const QString &strDecryptData, const QString &strPriKey)
{
    QByteArray priKeyArry = strPriKey.toUtf8();
    uchar* pPriKey = (uchar*)priKeyArry.data();
    BIO* pKeyBio = BIO_new_mem_buf(pPriKey, priKeyArry.length());
    if (pKeyBio == NULL) {
        return "";
    }

    RSA* pRsa = RSA_new();
    pRsa = PEM_read_bio_RSAPrivateKey(pKeyBio, &pRsa, NULL, NULL);
    if (pRsa == NULL) {
        BIO_free_all(pKeyBio);
        return "";
    }

    int nLen = RSA_size(pRsa);
    char* pPlainBuf = new char[nLen];
    memset(pPlainBuf, 0, nLen);

    //解密
    QByteArray decryptDataArry = strDecryptData.toUtf8();
    decryptDataArry = QByteArray::fromBase64(decryptDataArry);
    int nDecryptDataLen = decryptDataArry.length();
    uchar* pDecryptData = (uchar*)decryptDataArry.data();
    int nSize = RSA_private_decrypt(nDecryptDataLen,
                                    pDecryptData,
                                    (uchar*)pPlainBuf,
                                    pRsa,
                                    RSA_PKCS1_PADDING);

    QString strPlainData = "";
    if (nSize >= 0) {
        strPlainData = QByteArray(pPlainBuf, nSize);
    }

    //释放内存
    delete pPlainBuf;
    BIO_free_all(pKeyBio);
    RSA_free(pRsa);

    return strPlainData;
}

QString rsa::rsaPriDecryptHex(const QString &strDecryptData, const QString &strPriKey)
{
    QByteArray priKeyArry = strPriKey.toUtf8();
    uchar* pPriKey = (uchar*)priKeyArry.data();
    BIO* pKeyBio = BIO_new_mem_buf(pPriKey, priKeyArry.length());
    if (pKeyBio == NULL) {
        return "";
    }

    RSA* pRsa = RSA_new();
    pRsa = PEM_read_bio_RSAPrivateKey(pKeyBio, &pRsa, NULL, NULL);
    if (pRsa == NULL) {
        BIO_free_all(pKeyBio);
        return "";
    }

    int nLen = RSA_size(pRsa);
    char* pPlainBuf = new char[nLen];
    memset(pPlainBuf, 0, nLen);

    //解密
//    QByteArray decryptDataArry = strDecryptData.toUtf8();
//    decryptDataArry = QByteArray::fromBase64(decryptDataArry);
//    int nDecryptDataLen = decryptDataArry.length();
//    uchar* pDecryptData = (uchar*)decryptDataArry.data();
    unsigned char pDecryptData[1024] = {0};
    for(int i=0;i<strDecryptData.length()/2;i++){ pDecryptData[i] = strDecryptData.mid(2*i,2).toUInt(Q_NULLPTR,16);}
    int nDecryptDataLen = strDecryptData.length()/2;
    int nSize = RSA_private_decrypt(nDecryptDataLen,
                                    pDecryptData,
                                    (uchar*)pPlainBuf,
                                    pRsa,
                                    RSA_PKCS1_PADDING);

    QString strPlainData = "";
    if (nSize >= 0) {
        strPlainData = QByteArray(pPlainBuf, nSize);
    }

    //释放内存
    delete pPlainBuf;
    BIO_free_all(pKeyBio);
    RSA_free(pRsa);

    return strPlainData;
}
复制代码

 

使用如下

#include "rsa.h"

 

复制代码
{
            QString strPlainData_before = "123456";
            QString strPubKey = "";
            QString strPriKey = "";
            QString strEncryptData = "";
            QString strPlainData = "";

            strPubKey = ui->data_rsa_publickey->toPlainText();
            strPriKey = ui->data_rsa_privatekey->toPlainText();

            myDebugMsg(strPubKey);
            myDebugMsg(strPriKey);

            strEncryptData = m_rsa->rsaPubEncrypt(strPlainData_before,strPubKey);
            myDebugMsg("strEncryptData:"+strEncryptData);

            strPlainData = m_rsa->rsaPriDecrypt(strEncryptData, strPriKey);
            myDebugMsg("strPlainData:"+strPlainData);
            myDebugMsg("data:"+data);

            //QTimer::singleShot(3000, [=](){     } );
        }
复制代码

// 另一个方法

            QString strPriKey = ui->data_rsa_privatekey->toPlainText();
            QString strPlainData = m_rsa->rsaPriDecryptHex(strEncryptData, strPriKey);

            myDebugMsg("strEncryptData:"+strEncryptData);
            myDebugMsg("strPlainData:"+strPlainData);

            if(ui->data_rsa->text()==strPlainData){alarmInfo(-11);}
            else{alarmInfo(-12);}

 

 

 

注意公钥加密,私钥解密        或者       私钥解密 公钥加密

 

最后附赠上openssl已经打包好的动态库

 https://files-cdn.cnblogs.com/files/RYSBlog/openssl%E5%8A%A8%E6%80%81%E5%BA%93.zip

posted @   小城熊儿  阅读(4408)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示