目录
1.2 配置Qt工程的.pro文件,加入Windows下依赖的Openssl库和头文件
2.3 配置Qt工程的.pro文件,加入Linux下依赖的Openssl库和头文件
一.摘要
最近项目中,需要用到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版,需要开发版本。
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源码包
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++使用