Qt openssl rsa 加密解密

最近在处理加密问题,需要用到数字签名,查询资料得知采用rsa加密基本安全。关于rsa加密算法,网络上关于这类说明比较多。其实关于C++ + openssl + rsa的相关代码比较多,要么要积分,要么写的不是qt方面的。今天抽空整理出qt + openssl + rsa相关加密函数及实现。
首先在实现功能的时候出现的一些问题及解决方法。
1、采用openssl-1_1_0h版本
2、qt pro文件中增加动态库关联,这里是把openssl安装文件中的include和lib文件拷贝至qt项目目录下。
   INCLUDEPATH += ./include
   LIBS += libcrypto.lib \   
           libssl.lib 
3、openssl有两种生成key的方式,一种是通过openssl命令生成;一种是通过调用接口用代码生成。两者生成的私钥格式一致,
   但是公钥格式存在区别,从而导致调用接口不一样。
   代码生成的key标题为 -----BEGIN RSA PUBLIC KEY----- ,调用接口PEM_read_bio_RSAPublicKey;
   命令生成的key标题为 -----BEGIN PUBLIC KEY----- ,调用接口 PEM_read_bio_RSA_PUBKEY
4、若通过命令生成的key,拷贝至项目中使用时,需要注意格式,标题和每一行后的换行(/n)必须都带上。
5、由于传输的key都是QString类型,需要转化为uchar*。
   错误的方式: uchar* pPriKey = (uchar*)strPriKey.toUtf8().data();  
   正确的方式: QByteArray priKeyArry = strPriKey.toUtf8();
               uchar* pPriKey = (uchar*)priKeyArry.data(); 
6、代码中为方便查看生成的key,统一都转化base64格式,但是在解密的时候需要转化为uchar*。

这里仅处理小于128字节的数据加密,后续把分片加密整理出来。

代码实现如下:

#include 
#include 
#include 
#include 

// 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 rsa
{
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 void test ();
};

#endif // RSA_H
#include "rsa.h"
/** 
* @brief createRsaKey 生成秘钥对 
* @param strPubKey 公钥 
* @param strPriKey 私钥 
* @return 成功状态 
*/
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;
}

/**
 * @brief rsa_pri_encrypt 私钥加密
 * @param strClearData 明文
 * @param strPriKey 私钥
 * @return 加密后数据(base64格式)
 */
QString rsa::rsa_pri_encrypt_base64 (const QString& strClearData, 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 ( 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();     
    uchar* pClearData = (uchar*)clearDataArry.data();    
    int nSize = RSA_private_encrypt(nClearDataLen,                     
                                    pClearData,                                    
                                    (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;
}

/**
 * @brief rsa_pub_decrypt 公钥解密
 * @param strDecrypt 待解密数据(base64格式)
 * @param strPubKey 公钥
 * @return 明文
 */
QString rsa::rsa_pub_decrypt_base64(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* 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);
    }

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

/**
 * @brief rsa_pub_encrypt 公钥加密
 * @param strClearData 明文
 * @param strPubKey 私钥
 * @return 加密后数据(base64格式)
 */
QString rsa::rsa_pub_encrypt_base64 (const QString& strClearData, 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 clearDataArry = strClearData.toUtf8();
    int nClearDataLen = clearDataArry.length();
    uchar* pClearData = (uchar*)clearDataArry.data();
    int nSize = RSA_public_encrypt(nClearDataLen,
                                   pClearData,
                                   (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;
}

/** 
 * @brief rsa_pri_decrypt 私钥解密
 * @param strDecrypt 待解密数据(base64格式) 
 * @param strPriKey 私钥
 * @return 明文
 */
QString rsa::rsa_pri_decrypt_base64(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* 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_private_decrypt(nDecryptDataLen,
                                    pDecryptData,
                                    (uchar*)pClearBuf,
                                    pRsa,
                                    RSA_PKCS1_PADDING);
    QString strClearData = "";
    if ( nSize >= 0 ){
        strClearData = QByteArray(pClearBuf, nSize);
    }
    // 释放内存
    delete pClearBuf;
    BIO_free_all(pKeyBio);
    RSA_free(pRsa);
    return strClearData;
}

void rsa::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);
    qDebug() << strPubKey << endl;
    qDebug() << strPriKey << endl;
    qDebug() << "private key encrypt, public key decrypt";
    QString strClear = "hello";
    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"; 
    strEncryptData = rsa_pub_encrypt_base64 (strClear, strPubKey);
    qDebug() << strEncryptData; 
    strClearData = rsa_pri_decrypt_base64 (strEncryptData, strPriKey);
    qDebug() << strClearData;
}
 
 

你可能感兴趣的:(qt)