Qt ---windows和linux下调用Openssl库实现RSA算法

4 篇文章 0 订阅

目录

一.摘要

二.RSA算法

RSA算法

一文搞懂 RSA 算法

三.RSA算法C++代码实现

1. windows下:

1.1 安装Openssl

1.2 配置Qt工程的.pro文件,加入Windows下依赖的Openssl库和头文件

2. Linux下

2.1 下载Openssl源码包

2.2 配置、编译和安装Openssl

2.3 配置Qt工程的.pro文件,加入Linux下依赖的Openssl库和头文件

3. 代码实现

 新建RSA算法类MyRSA


 

一.摘要

最近项目中,需要用到RSA加解密算法实现对数据的加解密处理,但是Qt的算法库中并没有RSA,所以只能尝试着调用其它库。查看资料,发现Openssl和gmp(GNU MP数字运算库)都支持RSA,权衡后Openssl用的比较多,所以打算用openssl库来实现RSA算法。

 

二.RSA算法

RSA是目前使用最广泛的公钥密码体制之一。它是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。

详情参考:

RSA算法

一文搞懂 RSA 算法

大概就是,RSA加解密使用的密钥有两者方式:对称密钥(加密和解密使用同一种密钥的方式)和非对称密钥(加密和解密使用不同的密码的方式,即公私密钥对),一般公私密钥对的方式用的比较多。再则,就是公钥加密后需要对应私钥才能解密,同理私钥加密的得用对应的公钥才能解密。算法的原理和描述,在此,就不再赘述。

 

三.RSA算法C++代码实现

Qt,中需要用到Openssl,得注意版本相关性。Openssl的版本对Qt各个版本支持各不相同。可通过如下方式获知当前Qt版本支持的Openssl版本;

#include <QSslSocket>


qDebug() << QSslSocket::sslLibraryBuildVersionString();

例如:Qt 5.9.6 (MSVC 2015, 32 bit)支持的openssl最高版本为:OpenSSL 1.0.2j 26 Sep 2016。这里选择Openssl 1.0.2e。Windows下,只需要安装Openssl的安装版本,即可使用;Linux下,需要编译源码(arm下交叉编译),安装后,才能使用。

 

1. windows下:

1.1 安装Openssl

先下载windows下Openssl安装包,别选择Light版,需要开发版本。

Openssl官网

Win32OpenSSL-1_0_2e.exe

然后,按照安装步骤装好后,将安装目录下的lib/MinGW和include文件夹copy到Qt工程目录下;

lib/MinGW一览:

include文件夹如下:

 

1.2 配置Qt工程的.pro文件,加入Windows下依赖的Openssl库和头文件

    INCLUDEPATH += $$PWD/include
    LIBS += -L$$PWD/lib/MinGW -lssleay32
    LIBS += -L$$PWD/lib/MinGW -llibeay32

如此,windows下Openssl库可以正常使用。

 

2. Linux下

2.1 下载Openssl源码包

openssl-1.0.2e.tar.gz

 

2.2 配置、编译和安装Openssl

 配置,选项如下:

setarch i386 ./config no-asm shared --prefix=/***/openssl-1.0.2e/my_lib --cross-compile=arm-linux-gnueabihf-

此处使用的是交叉编译工具链arm-linux-gnueabihf-,--prefix=选项指定的是安装目录。然后,编译,安装即可:

make

make instal

注意:记得加setarch i386 好多都没加 不加去掉-m64 编译出来有问题

源码目录文件如下:

安装目录文件如下:

将lib和include放到Qt工程目录下。

 

2.3 配置Qt工程的.pro文件,加入Linux下依赖的Openssl库和头文件

    INCLUDEPATH += $$PWD/lib/openssl/include

    LIBS += -L/lib/ -lcrypto -lssl

实际用到的库文件为libcrypto.so.1.0.0和libssl.so.1.0.0,copy到目标arm设备上时,需要将这两个库文件重命名为libcrypto.so和libssl.so,比如我是放在目标设备的/lib/目录下,所以库链接时只需:LIBS += -L/lib/ -l crypto -lssl 即可。

 

3. 代码实现

新建RSA算法类MyRSA

头文件myrsa.h如下:

#ifndef MYRSA_H
#define MYRSA_H


#include <QDebug>
#include <openssl/rsa.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/err.h>

// define rsa public key
#define BEGIN_RSA_PUBLIC_KEY    "BEGIN RSA PUBLIC KEY"
#define BEGIN_PUBLIC_KEY        "BEGIN PUBLIC KEY"
#define KEY_LENGTH              1024                        // 密钥长度

class MyRSA
{
public:
/**
* @brief createRsaKey 生成秘钥对
* @param strPubKey 公钥
* @param strPriKey 私钥
* @return 状态
*/
static bool createRsaKey (QString& strPubKey, QString& strPriKey);
/**
* @brief rsa_pri_encrypt 私钥加密
* @param strClearData 明文
* @param strPriKey 私钥
* @return 加密后数据(base64格式)
*/
static QString rsa_pri_encrypt_base64 (const QString& strClearData, const QString& strPriKey);
/**
* @brief rsa_pub_decrypt 公钥解密
* @param strDecrypt 待解密数据(base64格式)
* @param strPubKey 公钥钥
* @return 明文
*/
static QString rsa_pub_decrypt_base64 (const QString& strDecryptData, const QString& strPubKey);
/**
* @brief rsa_pub_encrypt 公钥加密
* @param strClearData 明文
* @param strPubKey 私钥
* @return 加密后数据(base64格式)
*/
static QString rsa_pub_encrypt_base64 (const QString& strClearData, const QString& strPubKey);
/**
* @brief rsa_pri_decrypt 私钥解密
* @param strDecrypt 待解密数据(base64格式)
* @param strPriKey 私钥
* @return 明文
*/
static QString rsa_pri_decrypt_base64 (const QString& strDecryptData, const QString& strPriKey);

//=============================分段加解密=========================================
//公钥加解密
static QString encrypt_RSA_by_long_str_public_key(const QString& strPubKey, const std::string& data);
static std::string decrypt_RSA_by_long_str_public_key(std::string publicKey, const std::string& data);
//私钥加解密
static std::string encrypt_RSA_by_long_str_private_key(std::string privateKey, const std::string& data);
static QString decrypt_RSA_by_long_str_private_key(const QString& strPriKey, const std::string& data);

/**
 * @brief RSASignature::createRSA 载入密钥
 * @param key 密钥
 * @param publi 公钥1 私钥0
 * @return
 */

static RSA* create_RSA(unsigned char * key,int publi);


/**< 测试 */
static void test ();
};

#endif // MYRSA_H

myrsa.cpp源码:

#include "myrsa.h"
#include <iostream>

using namespace std;

/**
* @brief createRsaKey 生成秘钥对
* @param strPubKey 公钥
* @param strPriKey 私钥
* @return 成功状态
*/
bool MyRSA::createRsaKey (QString& strPubKey, QString& strPriKey)
{
     RSA *pRsa = RSA_generate_key(KEY_LENGTH, RSA_F4, NULL, NULL);       //RSA_3-->RSA_F4
     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;
}

/**
 * @brief rsa_pri_encrypt 私钥加密
 * @param strClearData 明文
 * @param strPriKey 私钥
 * @return 加密后数据(base64格式)
 */
QString MyRSA::rsa_pri_encrypt_base64 (const QString& strClearData, const QString& strPriKey)
{
    QString strEncryptData = "";
    QByteArray encryptData;
    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 ( pRsa == NULL ){
         BIO_free_all(pKeyBio);
         return "";
    }
    int nLen = RSA_size(pRsa);
    char* pEncryptBuf = new char[nLen];
    memset(pEncryptBuf, 0, nLen);
    QByteArray clearDataArry = strClearData.toUtf8();
    int nClearDataLen = clearDataArry.length();
//    qDebug() << "nClearDataLen = " << nClearDataLen;

    uchar* pClearData = (uchar*)clearDataArry.data();
//    int nSize = RSA_private_encrypt(nClearDataLen,          //字符串的长度
//                                    pClearData,             //字符串unsigned char*格式
//                                    (uchar*)pEncryptBuf,    //加密后的数据缓存
//                                    pRsa,
//                                    RSA_PKCS1_PADDING);     //1
//    QString strEncryptData = "";
//    if ( nSize >= 0 ){
//         QByteArray arry(pEncryptBuf, nSize);
//         strEncryptData = arry.toBase64();
//    }

    int pdBlock = nLen - 11;
    int nCount = (nClearDataLen / pdBlock) + 1;//分段次数

//    qDebug() << "nClearDataLen = " << nClearDataLen << "nCount = " << nCount << pdBlock;
    //分段加密
    for (int i = 0; i < nCount; i++)
    {
        int nSize = 0;
        pdBlock = (nClearDataLen > pdBlock) ? pdBlock : nClearDataLen;

        nSize = RSA_private_encrypt(pdBlock,
                                   pClearData,
                                   (uchar*)pEncryptBuf,
                                   pRsa,
                                   RSA_PKCS1_PADDING);
        pClearData += pdBlock;      //指针往前移
        nClearDataLen -= pdBlock;

        if ( nSize >= 0 ){
            QByteArray arry(pEncryptBuf, nSize);
            encryptData.append(arry);
//            qDebug() << "strEncryptData = " << strEncryptData;
        }
//        qDebug() << "nSize = " << nSize;
    }
    strEncryptData += encryptData.toBase64();       //最后才转,很重要,否则后面解密不成功


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

/**
 * @brief rsa_pub_decrypt 公钥解密
 * @param strDecrypt 待解密数据(base64格式)
 * @param strPubKey 公钥
 * @return 明文
 */
QString MyRSA::rsa_pub_decrypt_base64(const QString& strDecryptData, const QString& strPubKey)
{
    QString strClearData = "";
    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* pClearBuf = new char[nLen];
    memset(pClearBuf, 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*)pClearBuf,
//                                   pRsa,
//                                   RSA_PKCS1_PADDING);
//    QString strClearData = "";
//    if ( nSize >= 0 ){
//        strClearData = QByteArray(pClearBuf, nSize);
//    }

    int pdBlock = nLen;
    int nCount = (nDecryptDataLen / pdBlock) + 1;//分段次数
//    qDebug() << "nClearDataLen = " << nDecryptDataLen << "nCount = " << nCount << pdBlock;

    //分段解密
    for (int i = 0; i < nCount; i++)
    {
        int nSize = 0;

        pdBlock = (nDecryptDataLen > pdBlock) ? pdBlock : nDecryptDataLen;

        nSize = RSA_public_decrypt(pdBlock,
                                   pDecryptData,
                                   (uchar*)pClearBuf,
                                   pRsa,
                                   RSA_PKCS1_PADDING);
        pDecryptData += pdBlock;        //加密数据指针往前移
        nDecryptDataLen -= pdBlock;

            if ( nSize >= 0 ){
                strClearData += QByteArray(pClearBuf, nSize);

//                qDebug() << "nSize " << nSize;
//                qDebug() << "strClearData = " << strClearData;
            }
//            qDebug() << "nSize " << nSize;
    }

    // 释放内存
    delete pClearBuf;
    BIO_free_all(pKeyBio);
    RSA_free(pRsa);
    return strClearData;
}

/**
 * @brief rsa_pub_encrypt 公钥加密
 * @param strClearData 明文
 * @param strPubKey 私钥
 * @return 加密后数据(base64格式)
 */
QString MyRSA::rsa_pub_encrypt_base64 (const QString& strClearData, const QString& strPubKey)
{
    qDebug() << "rsa_pub_encrypt_base64 start...";
    QString strEncryptData;
    QByteArray encryptData;
    QByteArray pubKeyArry = strPubKey.toUtf8();
    uchar* pPubKey = (uchar*)pubKeyArry.data();
    BIO* pKeyBio = BIO_new_mem_buf(pPubKey, pubKeyArry.length());
    if (pKeyBio == NULL){
        return "pKeyBio = NULL";
    }
    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 "Rsa = NULL";
    }

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


    QByteArray clearDataArry = strClearData.toUtf8();
    int nClearDataLen = clearDataArry.length();
    uchar* pClearData = (uchar*)clearDataArry.data();

    int pdBlock = nLen - 11;
    int nCount = (nClearDataLen / pdBlock) + 1;//分段次数

//    qDebug() << "nClearDataLen = " << nClearDataLen << "nCount = " << nCount << pdBlock;

    //分段加密
    for (int i = 0; i < nCount; i++)
    {
        int nSize = 0;
        pdBlock = (nClearDataLen > pdBlock) ? pdBlock : nClearDataLen;

//        qDebug() << "RSA_public_encrypt start...";
        nSize = RSA_public_encrypt(pdBlock,
                                   pClearData,
                                   (unsigned char*)pEncryptBuf,
                                   pRsa,
                                   RSA_PKCS1_PADDING);


//        qDebug() << "RSA_public_encrypt mid...";
        pClearData += pdBlock;      //指针往前移
        nClearDataLen -= pdBlock;

//        qDebug() << "RSA_public_encrypt end...";
        if ( nSize >= 0 ){
            QByteArray arry((char*)pEncryptBuf, nSize);
            encryptData.append(arry);
//            qDebug() << "strEncryptData = " << strEncryptData;
        }
//        qDebug() << "nSize = " << nSize;
    }
    strEncryptData += encryptData.toBase64();       //最后才转,很重要,否则后面解密不成功

//    qDebug() << "rsa_pub_encrypt_base64 end...";
    // 释放内存
    delete pEncryptBuf;
    BIO_free_all(pKeyBio);
    RSA_free(pRsa);
    return strEncryptData;
}

/**
 * @brief rsa_pri_decrypt 私钥解密
 * @param strDecrypt 待解密数据(base64格式)
 * @param strPriKey 私钥
 * @return 明文
 */
QString MyRSA::rsa_pri_decrypt_base64(const QString& strDecryptData, const QString& strPriKey)
{
    QString strClearData = "";
    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* pClearBuf = new char[nLen];
    memset(pClearBuf, 0, nLen);

    //解密
    QByteArray decryptDataArry = strDecryptData.toUtf8();
    decryptDataArry = QByteArray::fromBase64(decryptDataArry);
    int nDecryptDataLen = decryptDataArry.length();
    uchar* pDecryptData = (uchar*)decryptDataArry.data();

//    qDebug() << "decryptDataArry === " <<  decryptDataArry.toHex().toUpper();

    int pdBlock = nLen;
    int nCount = (nDecryptDataLen / pdBlock) + 1;//分段次数
//    qDebug() << "nClearDataLen = " << nDecryptDataLen << "nCount = " << nCount << pdBlock;

    //分段解密
    for (int i = 0; i < nCount; i++)
    {
        int nSize = 0;

        pdBlock = (nDecryptDataLen > pdBlock) ? pdBlock : nDecryptDataLen;

        nSize = RSA_private_decrypt(pdBlock,
                                    pDecryptData,
                                    (uchar*)pClearBuf,
                                    pRsa,
                                    RSA_PKCS1_PADDING);
        pDecryptData += pdBlock;        //加密数据指针往前移
        nDecryptDataLen -= pdBlock;

            if ( nSize >= 0 ){
                strClearData += QByteArray(pClearBuf, nSize);

//                qDebug() << "nSize " << nSize;
//                qDebug() << "strClearData = " << strClearData;
            }
//            qDebug() << "nSize " << nSize;
    }

    // 释放内存
    delete pClearBuf;
    BIO_free_all(pKeyBio);
    RSA_free(pRsa);
    return strClearData;
}



void MyRSA::test()
{
    /**< rsa private/public key 若从文件中拷贝出来,需要注意保存元先文件格式,即换行符需要带上,包括最后一行的换行符 */
    QString strPriKey = "";
    QString strPubKey = "";
    /**
     *  用代码生成的key与openssl命令生成的key区别:
     *  1、代码生成key,标题为 -----BEGIN RSA PUBLIC KEY-----,openssl命令生成key, 标题为 -----BEGIN PUBLIC KEY-----
     *  2、获取RSA函数不同,代码生成key,用PEM_read_bio_RSAPublicKey,openssl命令生成key,用PEM_read_bio_RSA_PUBKEY
    */
    createRsaKey(strPubKey, strPriKey);
    cout << strPubKey.toStdString() << endl;
    cout << strPriKey.toStdString() << endl;

    QString strClear = "laneNo:00,laneType:06,proListNo:4301092020112416072864743E8B00000000,provinceCode:4301,psamNo:4301020100000032,random:64743E8B,roadCode:0000000000,roadName:000,stationCode:0000000000,stationName:长沙,stationType:00,terminalTime:2020-11-24 16:07:28";
    qDebug() << "private key encrypt, public key decrypt";
    QString strEncryptData = rsa_pri_encrypt_base64 (strClear, strPriKey);
    qDebug() << strEncryptData;
    QString strClearData = rsa_pub_decrypt_base64 (strEncryptData, strPubKey);
    qDebug() << strClearData;

//    qDebug() << "public key encrypt, private key decrypt";
//    QString strEncryptData = rsa_pub_encrypt_base64 (strClear, strPubKey);
//    qDebug() << strEncryptData;
//    QString strClearData = rsa_pri_decrypt_base64 (strEncryptData, strPriKey);
//    qDebug() << strClearData;

//    QString strEncryptData = encrypt_RSA_by_long_str_public_key(strPubKey, strClear.toStdString());
//    qDebug() << strEncryptData;
//    QString strClearData = decrypt_RSA_by_long_str_private_key(strPriKey, strEncryptData.toStdString());
//    qDebug() << strClearData;
}


//=====================================分段加解密====================================================
/*
 * 公钥加密
 */
QString MyRSA::encrypt_RSA_by_long_str_public_key(const QString& strPubKey, const std::string& data)
{
    QString strRet;
    ///创建RSA指针
//    RSA* rsa = create_RSA((unsigned char*)publicKey.c_str(), 1);
    qDebug() << "pk";
    QByteArray pubKeyArry = strPubKey.toUtf8();
    uchar* pPubKey = (uchar*)pubKeyArry.data();
    BIO* pKeyBio = BIO_new_mem_buf(pPubKey, pubKeyArry.length());
    if (pKeyBio == NULL){
        return "ERROR";
    }
    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 "ERROR";
    }

    int len = RSA_size(pRsa);

    char* decryptedText = (char*)malloc(len + 1);
    memset(decryptedText, 0, len + 1);

    int nClearDataLen = data.length();

    int pdBlock = len - 11;
    int nCount = (nClearDataLen / pdBlock) + 1;//分段次数
    qDebug() << "nClearDataLen" << nClearDataLen << "pdBlock" << pdBlock << "nCount" << nCount;

    unsigned char* pClearData = (unsigned char*)data.c_str();
    //分段加密
    for (int i = 0; i < nCount; i++)
    {
        int nSize = 0;
        pdBlock = (nClearDataLen > pdBlock) ? pdBlock : nClearDataLen;
        nSize = RSA_public_encrypt(pdBlock, (const unsigned char*)pClearData, (unsigned char*)decryptedText, pRsa, RSA_PKCS1_PADDING);
        pClearData += pdBlock;
        nClearDataLen -= pdBlock;

        if (nSize >= 0)
        {
//            strRet += std::string(decryptedText, nSize);
            QByteArray arry(decryptedText, nSize);
            strRet += arry.toBase64();
        }
    }

    // 释放内存
    delete decryptedText;
    RSA_free(pRsa);
    return strRet;
}
/*
 * 公钥解密
 */
std::string MyRSA::decrypt_RSA_by_long_str_public_key(std::string publicKey, const std::string& data)
{
    std::string strRet;
    ///创建RSA指针
    RSA* rsa = create_RSA((unsigned char*)publicKey.c_str(), 1);

    int len = RSA_size(rsa);
    char* decryptedText = (char*)malloc(len + 1);
    memset(decryptedText, 0, len + 1);

    int nClearDataLen = data.length();

    int pdBlock = len;
    int nCount = (nClearDataLen / pdBlock) + 1;//分段次数
    unsigned char* pClearData = (unsigned char*)data.c_str();
    //分段解密
    for (int i = 0; i < nCount; i++)
    {
        int nSize = 0;

        pdBlock = (nClearDataLen > pdBlock) ? pdBlock : nClearDataLen;
        nSize = RSA_public_decrypt(pdBlock, (const unsigned char*)pClearData, (unsigned char*)decryptedText, rsa, RSA_PKCS1_PADDING);
        pClearData += pdBlock;
        nClearDataLen -= pdBlock;

        if (nSize >= 0)
        {
            strRet += std::string(decryptedText, nSize);
        }
    }
    delete decryptedText;
    // 释放内存
    RSA_free(rsa);
    return strRet;
}

/*
 * 私钥加密
 */
std::string MyRSA::encrypt_RSA_by_long_str_private_key(std::string privateKey, const std::string& data)
{
    std::string strRet;
    ///创建RSA指针
    RSA* rsa = create_RSA((unsigned char*)privateKey.c_str(), 0);

    int len = RSA_size(rsa);

    char* decryptedText = (char*)malloc(len + 1);
    memset(decryptedText, 0, len + 1);

    int nClearDataLen = data.length();

    int pdBlock = len - 11;         //padding占11位
    int nCount = (nClearDataLen / pdBlock) + 1;//分段次数
    unsigned char* pClearData = (unsigned char*)data.c_str();
    //分段加密
    for (int i = 0; i < nCount; i++)
    {
        int nSize = 0;
        pdBlock = (nClearDataLen > pdBlock) ? pdBlock : nClearDataLen;
        nSize = RSA_private_encrypt(pdBlock, (const unsigned char*)pClearData, (unsigned char*)decryptedText, rsa, RSA_PKCS1_PADDING);
        pClearData += pdBlock;
        nClearDataLen -= pdBlock;

        if (nSize >= 0)
        {
            strRet += std::string(decryptedText, nSize);
        }
    }

    // 释放内存
    delete decryptedText;
    RSA_free(rsa);
    return strRet;
}
/*
 * 私钥解密
 */
QString MyRSA::decrypt_RSA_by_long_str_private_key(const QString& strPriKey, const std::string& data)
{
    QString strRet;
    ///创建RSA指针
//    RSA* rsa = create_RSA((unsigned char*)privateKey.c_str(), 0);
    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 "error";
    }


    int len = RSA_size(pRsa);
    char* decryptedText = (char*)malloc(len + 1);
    memset(decryptedText, 0, len + 1);

    int nClearDataLen = data.length();
    int pdBlock = len;
    int nCount = (nClearDataLen / pdBlock) + 1;//分段次数
    unsigned char* pClearData = (unsigned char*)data.c_str();
    //分段解密
    for (int i = 0; i < nCount; i++)
    {
        int nSize = 0;

        pdBlock = (nClearDataLen > pdBlock) ? pdBlock : nClearDataLen;
        nSize = RSA_private_decrypt(pdBlock, (const unsigned char*)pClearData, (unsigned char*)decryptedText, pRsa, RSA_PKCS1_PADDING);
        pClearData += pdBlock;
        nClearDataLen -= pdBlock;

        if (nSize >= 0)
        {
//            strRet += std::string(decryptedText, nSize);
            strRet += QByteArray(decryptedText, nSize);

            qDebug() << "nSize = " << nSize;
        }
    }
    delete decryptedText;
    // 释放内存
    RSA_free(pRsa);
    return strRet;
}

/**
 * @brief RSASignature::createRSA 载入密钥
 * @param key 密钥
 * @param publi 公钥1 私钥0
 * @return
 */

RSA * MyRSA::create_RSA(unsigned char *key,int publi)
{
    RSA *rsa= NULL;
    BIO *keybio ;
    keybio = BIO_new_mem_buf(key, -1);

    if (keybio==NULL){
        qDebug()<< "Failed to create key BIO";
        return 0;
    }

    if(publi){
        rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL);
    } else {
        rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);
    }

    if(rsa == NULL){
        qDebug()<< "Failed to create RSA";
    }
    return rsa;
}

说明:

1. 此RSA算法类实现了公私密钥对的生成、公钥加解密、私钥加解密,在此基础上增加了分段加解密。如果不分段进行加解密运算,RSA算法会对加密的字符串长度有限制:

比如,密钥长度为1024b,则可进行

加解密的字符串长度最大 = 1024/8 - 11(padding),即117字节。

这对超长字符串的加解密不友好,你又不能任性的增加密钥的长度,因为密钥越长,加解密运算越慢,所以只能进行分段加解密;

2.原本是针对std::string进行加解密,由于在Qt下,我引入了QString 和 QByteArray,大家按需更改;

3.具体的调用方法可以看test();

4.与我对接的是使用JAVA,JAVA对RSA算法支持很完善,但是有一点需要注意,JAVA所用的私钥密钥与Openssl所用的私钥密钥格式有所不同,JAVA的为PKCS8格式,而Openssl则为PKCS1格式,需要相应的转换,方法如下:

生成私钥

openssl genrsa -out rsa_private_key.pem 1024

Java使用的私钥

Java使用的时候需要再次编码,转换成pkcs8编码,使用如下命令:

 openssl pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt

由私钥生成公钥

openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout

客户端加密使用公钥rsa_public_key.pem 来加密, Java服务端使用pkcs8_rsa_private_key.pem 来解密。

 

 

以上就是在Qt下,通过Openssl库,来实现RSA算法。整个过程还是很头大的,希望以后Qt可以对算法有更多的支持吧。

以下是一些再次过程中提供了思路博客地址,此时此刻也是由衷的感谢他们无私的分享。

 

参考:

https://blog.csdn.net/sinat_14854721/article/details/100555078

OpenSSL C++ RSA 超长string 加密解密

用openssl进行rsa的加密与解密(linux,C++版)

C++使用OpenSSL进行RSA加密和解密

使用OpenSSL生成RSA密钥对供Java和C++使用

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值