Qt5使用openssl实现RSA数字签名

来源:互联网 发布:人物卡通设计软件 编辑:程序博客网 时间:2024/06/08 15:00

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 <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/bn.h>
#include <openssl/bio.h>
#include <openssl/evp.h>

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+AaS9Esc6FdzZ716bqFUTyhTAKU78yUfaG3GSmPH+HyIZIiZnqlU9Z0MEXhFY6hMgI20ZcuZAAyz6G1hQeaJt1xLSdUblaB5fV6mMPcCuKTgctjq9HJhw47e/iMY+lj+7+30H4Vo43+xLA4RBmUv4M0AXUnQIDAQAB-----END PUBLIC KEY-----

-----BEGIN RSA PRIVATE KEY-----MIICXAIBAAKBgQCfbQTubOxaSqao97+AaS9Esc6FdzZ716bqFUTyhTAKU78yUfaG3GSmPH+HyIZIiZnqlU9Z0MEXhFY6hMgI20ZcuZAAyz6G1hQeaJt1xLSdUblaB5fV6mMPcCuKTgctjq9HJhw47e/iMY+lj+7+30H4Vo43+xLA4RBmUv4M0AXUnQIDAQABAoGBAIHzL03ZY17F8stQBrz5ABqShLCt169ivR+ZbrXwcpQ4Z2TxAm4zP6dxMNLRVQPTha59Pk0LqBkvOcpBaXwuoE6zaILz9xbyWyZzC/zecq4P4NJRGesdo2yTnnhb0dJSOAVydCGuTCbbjS/F4Z854NJ8392+h0XCjwJsV+17apVRAkEAy1A7rG0AyYp2n7b3R0RbDGMbo3Zaxpx2kLHCUOGM6+HLmMuQmff4Y37bsvK27X4IGomptl1+iAJoGGLeM/+7EwJBAMi9S6Uk2xgf9FqQa4BL/SyOkgjntH69LLUstA+69jSb4A/FTKG6R6g09qCARb4MLx6LQwnRA6guE7hma68/948CQGpkbwW4+Nt+iLrlbRsvKxIdXt44ViJuyCDJ1Kysiyj4vKkVhXL8709pmCBZoN5AwI7akSPsYwVbdQul2S+O2F8CQBN8nM1JSKOM5pGsF2N6/PbIWFDY/WKYRrDHyCsGwUPWJegiBRBmHvKrQY3PJfYPBLv4VOetDKfU4UEzYBzBHu0CQDaoJbKyumkQXcZXT5cQ0n8Tu5islB8XeItUqAI3Y9uKZVLTsoTLVAqMyJsEDDIK8AO580NEF++6nzig/LpOvuU=-----END RSA PRIVATE KEY-----

真正使用的时候公钥密钥只需要生成一次,使用密钥生成的签名里面含有不可显示字符,所以如果输出显示要么转为16进制,要么进行base64编码;

提供上面的密钥的鲁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

原创粉丝点击