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 <QDebug>
#include <openssl/rsa.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 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;
}
 
 
  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: RSA是一种非对称加密算法,使用公钥加密和私钥解密。在Linux和Qt环境下,我们可以使用OpenSSL库对RSA进行加密和解密操作。 在Qt中使用OpenSSL库,需要在.pro文件中加入如下语句: LIBS += -lssl -lcrypto 这样就可以链接OpenSSL库。 RSA算法分为公钥加密和私钥解密两个步骤。在Qt中,我们可以使用该库中的RSA_generate_key函数生成一对公私钥,该函数需要传入一个整型值作为密钥位数。 生成密钥对后,我们可以使用RSA_public_encrypt函数和RSA_private_decrypt函数分别对明文进行加密和密文进行解密操作。 下面是一个简化版的RSA加密算法实现: #include <openssl/rsa.h> #include <openssl/pem.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { // 生成密钥对 RSA *r = RSA_generate_key(1024, RSA_F4, NULL, NULL); // 明文和密文 unsigned char plaintext[100] = "Hello, world!"; unsigned char ciphertext[1024] = {0}; unsigned char output[100] = {0}; // 加密 int len = RSA_public_encrypt(strlen((const char *)plaintext), plaintext, ciphertext, r, RSA_PKCS1_PADDING); printf("Ciphertext: %s\n", ciphertext); // 解密 len = RSA_private_decrypt(len, ciphertext, output, r, RSA_PKCS1_PADDING); printf("Plaintext: %s\n", output); return 0; } 这是一个简单的RSA加密解密程序,其中使用了OpenSSL库中的RSA_generate_key、RSA_public_encrypt和RSA_private_decrypt函数分别生成密钥对、加密明文和解密密文。 ### 回答2: RSA加密算法是一种非对称加密算法,常用于信息安全领域。使用Qt实现RSA加密解密,需要先了解RSA算法及其原理。 首先,RSA算法中需要生成一对公私钥,公钥用于加密,私钥用于解密。生成公私钥的过程如下: 1. 随机选择两个不同的质数p和q 2. 计算n=p*q 3. 计算欧拉函数φ(n)=(p-1)*(q-1) 4. 选择一个整数e(1<e<φ(n)),e与φ(n)互质 5. 计算d,满足d*e ≡ 1 (mod φ(n)) 6. 公钥为(n,e),私钥为(n,d) 加密过程如下: 1. 将待加密数据转换为整数m(0<=m<n) 2. 计算密文c=m^e (mod n) 解密过程如下: 1. 接收到密文c 2. 计算明文m=c^d (mod n) 使用Qt实现RSA加密解密,可以参考以下步骤: 1. 生成公私钥对:随机选择两个质数p和q,计算n、φ(n)、e和d,得到公钥(n,e)和私钥(n,d)。 2. 加密:将待加密数据转换为整数m,计算密文c=m^e(mod n)。 3. 解密:接收到密文c,计算明文m=c^d(mod n)。 4. 实现一个简化版的RSA加密算法:通过Qt提供的大数类,实现上述步骤。 5. 测试:输入待加密的字符串,将其转换为整数后加密,再将密文解密并转回字符串,与原字符串进行比较,验证加解密是否正确。 总的来说,使用Qt实现RSA加密解密需要了解RSA算法原理,并掌握Qt提供的大数类。在实现过程中,需要注意数据类型的转换和边界处理,保证算法的正确性和运行效率。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值