1、环境安装
win7 64
安装qt-opensource-windows-x86-5.9.0.exe或更高版本,下载地址
安装Win32OpenSSL-1_0_2L.exe 下载地址,最新版本可能因为pro配置问题,总不成功,希望大家提醒
2、在Qt5工程的pro中 填写
LIBS += -LC:/OpenSSL-Win32/lib/MinGW -llibeay32
LIBS += -LC:/OpenSSL-Win32/lib/MinGW -lssleay32
INCLUDEPATH += $$quote(C:/OpenSSL-Win32/include)
添加头文件
#include
#include
#include
#include
#include
3、添加代码
void MainWindow::createRSAKey()
{
//创建目录
QString strPath = "./key";
QDir dir;
if(dir.exists(strPath) == false)
{
dir.mkpath(strPath);//创建目录
}
BIGNUM *bne = BN_new();
int ret = BN_set_word(bne,RSA_F4);/* 设置随机数长度 */
RSA *rsa = RSA_new();
ret = RSA_generate_key_ex(rsa,1024,bne,NULL);/* 密钥长度1024 生成RSA密钥对 */
if(ret != 1)
{
QMessageBox::information(this,"错误提示","生成RSA密钥错误!无法实现后续数字签名!",QMessageBox::Yes);
return;
}
/* 提取私钥 */
FILE *filename = NULL;
filename = fopen("./key/privateKey.pem", "wb");
PEM_write_RSAPrivateKey(filename, rsa, NULL, NULL, 0, NULL, NULL);
fclose(filename);
filename = NULL;
/* 提取公钥 */
unsigned char *n_b = (unsigned char *)calloc(RSA_size(rsa), sizeof(unsigned char));
unsigned char *e_b = (unsigned char *)calloc(RSA_size(rsa), sizeof(unsigned char));
int n_size = BN_bn2bin(rsa->n, n_b);
int b_size = BN_bn2bin(rsa->e, e_b);
RSA *pubrsa = RSA_new();
pubrsa->n = BN_bin2bn(n_b, n_size, NULL);
pubrsa->e = BN_bin2bn(e_b, b_size, NULL);
// //另一种格式的公钥输出
// filename = fopen("./key/publicKeyRSA.pem", "wb");
// PEM_write_RSAPublicKey(filename, pubrsa);
// fclose(filename);
// filename = NULL;
filename = fopen("./key/publicKey.pem", "wb");
PEM_write_RSA_PUBKEY(filename, pubrsa);
fclose(filename);
filename = NULL;
RSA_free(pubrsa);
RSA_free(rsa);
}
编译链接没有问题,运行发现当执行到PEM_write_RSAPrivateKey时报错:OPENSSL_Uplink(67C97000,08): no OPENSSL_Applink
按照网络上的方法尝试
在main文件中的包含头文件的下方加入OpenSSL的链接头文件(经测试放在在调用的mainwidow.cpp中也可以)
extern "C"{
#include "openssl/applink.c"
};
报错
C:\OpenSSL-Win32\include\openssl\applink.c:-1: In function 'void** OPENSSL_Applink()':
C:\OpenSSL-Win32\include\openssl\applink.c:95: error: invalid conversion from 'void* (*)()' to 'void*' [-fpermissive]
OPENSSL_ApplinkTable[APPLINK_STDIN] = app_stdin;
……
大概是说指针转换出错,全部加上强转,比如
将OPENSSL_ApplinkTable[APPLINK_STDIN] = app_stdin;改为OPENSSL_ApplinkTable[APPLINK_STDIN] =(void*)app_stdin;
编译通过,运行不闪退了
要注意生成公钥和密钥的PEM格式,因为要对应相应的导入函数
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfbQTubOxaSqao97+AaS9Esc6F
dzZ716bqFUTyhTAKU78yUfaG3GSmPH+HyIZIiZnqlU9Z0MEXhFY6hMgI20ZcuZAA
yz6G1hQeaJt1xLSdUblaB5fV6mMPcCuKTgctjq9HJhw47e/iMY+lj+7+30H4Vo43
+xLA4RBmUv4M0AXUnQIDAQAB
-----END PUBLIC KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCfbQTubOxaSqao97+AaS9Esc6FdzZ716bqFUTyhTAKU78yUfaG
3GSmPH+HyIZIiZnqlU9Z0MEXhFY6hMgI20ZcuZAAyz6G1hQeaJt1xLSdUblaB5fV
6mMPcCuKTgctjq9HJhw47e/iMY+lj+7+30H4Vo43+xLA4RBmUv4M0AXUnQIDAQAB
AoGBAIHzL03ZY17F8stQBrz5ABqShLCt169ivR+ZbrXwcpQ4Z2TxAm4zP6dxMNLR
VQPTha59Pk0LqBkvOcpBaXwuoE6zaILz9xbyWyZzC/zecq4P4NJRGesdo2yTnnhb
0dJSOAVydCGuTCbbjS/F4Z854NJ8392+h0XCjwJsV+17apVRAkEAy1A7rG0AyYp2
n7b3R0RbDGMbo3Zaxpx2kLHCUOGM6+HLmMuQmff4Y37bsvK27X4IGomptl1+iAJo
GGLeM/+7EwJBAMi9S6Uk2xgf9FqQa4BL/SyOkgjntH69LLUstA+69jSb4A/FTKG6
R6g09qCARb4MLx6LQwnRA6guE7hma68/948CQGpkbwW4+Nt+iLrlbRsvKxIdXt44
ViJuyCDJ1Kysiyj4vKkVhXL8709pmCBZoN5AwI7akSPsYwVbdQul2S+O2F8CQBN8
nM1JSKOM5pGsF2N6/PbIWFDY/WKYRrDHyCsGwUPWJegiBRBmHvKrQY3PJfYPBLv4
VOetDKfU4UEzYBzBHu0CQDaoJbKyumkQXcZXT5cQ0n8Tu5islB8XeItUqAI3Y9uK
ZVLTsoTLVAqMyJsEDDIK8AO580NEF++6nzig/LpOvuU=
-----END RSA PRIVATE KEY-----
提供上面的密钥的鲁123456789的数字签名(十六进制输出),也方便大家对照RSA签名
openssl的RSA数字签名函数RSA_sign没有执行摘要算法,所以要对明文先进行摘要算法SHA1,否则和C# JAVA生成的RSA签名是不一致的!
代码:
void MainWindow::CreateSignature(QByteArray const &strxml,unsigned char *bSign,size_t *iSignlen)
{
unsigned char *bData = NULL;//报文
bData = (unsigned char*)(strxml.data());
size_t iDatalen = strxml.size();
LoadRSA();//这里可以放在构造函数执行一次加载进来就可以了
unsigned char szTmp[20]={0};
SHA1(bData, iDatalen, szTmp);//一定先生成摘要
int ret = RSA_sign(NID_sha1,szTmp,20,bSign,iSignlen,p_rsa);
if(ret!=1)
{
QMessageBox::information(this,"错误提示","生成签名失败!",QMessageBox::Yes);
}
}
完整的
Qt5工程,以及
Win32OpenSSL-1_0_2L.exe都 上传到CSDN,方便大家参考,欢迎下载评论
参考文献
Windows下openssl的下载安装和使用
openssl之RSA编程
C# RSACryptoServiceProvider加密解密签名验签和DESCryptoServiceProvider加解密
保存openssl中RSA密钥对
SHA1WithRSA签名使用openssl 实现
Qt之OpenSSL
QT添加openssl的方法
openssl编程出现no OPENSSL_Applink
Qt openssl配置,OPENSSL_Applink错误
How to Include OpenSSL in a Qt project