环境篇-Windows下安装OpenSSL, 【QT】windows下OpenSSL的使用,RSA加解密


注意:关于libeay32.dll和ssleay32.dll (在1.1.x之后的版本中,名字是libssl.dll和libcrypto.dll)

在1.0.x之前的版本中,文件为libeay32.dll和ssleay32.dll,在1.1.x之后的版本中,名字是libssl.dll和libcrypto.dll

可能读者在搜索资料的过程中,发现有的地方说要拷贝libeay32.dll和ssleay32.dll,有的地方说要拷贝libssl-1_1.dll和libcrypto-1_1.dll。到底需要哪个?还是两者都要?

答案在OpenSSL git仓库日志中,找到分支OpenSSL-1_1_0-stable,查看日志,在以下提交中有对应的描述:

SHA-1: 6928b6171ada6d0de5a024a188dc7a68094d2dca
* Change names of ordinals and libs, libeay => libcrypto and ssleay => libssl
Reviewed-by: Rich Salz <rsalz@openssl.org>

也就是说,

libeay32.dll和ssleay32.dll是OpenSSL v1.1.0之前版本才有的库。
从OpenSSL v1.1.0开始,libeay32.dll=>libcrypto,ssleay32.dll=>libssl。

OpenSSL加密算法库使用系列教程

https://blog.csdn.net/zyhse/article/details/108026800

在这里插入图片描述

windows如果快速安装OpenSSL(懒人安装)

Chapter1 本文属于《OpenSSL加密算法库使用系列教程》之一,欢迎查看其它文章

原文链接:https://blog.csdn.net/zyhse/article/details/108186278

OpenSSL是一个功能丰富且开源的安全工具箱,它提供的主要功能有:SSL协议实现(包括SSLv2、SSLv3和TLSv1)、大量软算法(对称/非对称/摘要)、大数运算、非对称算法密钥生成、ASN.1编解码库、证书请求(PKCS10)编解码、数字证书编解码、CRL编解码、OCSP协议、数字证书验证、PKCS7标准实现和PKCS12个人数字证书格式实现等功能。

OpenSSL采用C语言作为开发语言,这使得它具有优秀的跨平台性能,OpenSSL支持:

  • Linux
  • UNIX
  • Windows
  • Mac等平台

OpenSSL的github地址:https://github.com/openssl/openssl

OpenSSL工具箱,主要包括以下三个组件:

  • openssl:多用途的命令行工具
  • libcrypto:加密算法库
  • libssl:加密模块应用库,实现了ssl及TLS协议

一、下载安装包

如果不想自己编译源码,那么可以直接去下载编译好的二进制文件进行安装,省事方便。

下载地址:http://slproweb.com/products/Win32OpenSSL.html
在这里插入图片描述

有4种安装包:

  • Win64 OpenSSL v1.1.1i Light,安装Win64 OpenSSL v1.1.1i最常用的软件包
  • Win64 OpenSSL v1.1.1i,安装Win64 OpenSSL v1.1.1i完整软件包
  • Win32 OpenSSL v1.1.1i Light,安装Win32 OpenSSL v1.1.1i最常用的软件包
  • Win32 OpenSSL v1.1.1i,安装Win32 OpenSSL v1.1.1i完整软件包
    我们选择下载“Win64 OpenSSL v1.1.1i”。

二、安装

对下载的Win64OpenSSL-1_1_1i.exe,进行安装。

一般默认安装,但安装步骤中有一步,“Select Additional Tasks”,让选择OpenSSL的dll拷贝到什么地方,如下:
在这里插入图片描述

建议,不要拷贝到系统目录下,如果其他软件使用的OpenSSL版本与你安装这个版本不同,可能导致该软件无法使用。所以让这些dll待在OpenSSL安装目录下即可。

最后一步,是否捐款,如下:
在这里插入图片描述

看个人情况,全取消就是不捐。

安装完毕。

安装目录下内容:

在这里插入图片描述

三、验证安装是否正确

直接在cmd中,输入命令,查看OpenSSL版本

openssl version

结果,并不是我们安装的1.1.1i版

在这里插入图片描述

原因: 如果电脑上已经安装过其他软件,比如Git、VMware、Strawberry等,那么他们都自带了openssl,如下:
在这里插入图片描述

所以,当你在cmd中使用openssl命令时,可能会调用到其他版本的openssl。

解决办法: 将openssl 1.1.1i版本命令行工具路径添加到,系统变量Path第一条,以保证它首先被找到。

在这里插入图片描述

再次验证,查看OpenSSL版本正确。

在这里插入图片描述

Chapter2 【QT】windows下OpenSSL的使用,RSA加解密

原文链接:https://blog.csdn.net/weixin_48618536/article/details/130905460

前言

从古至今,如何用最有效的加密手段保护信息的安全性使之不被窃取、篡改或者破坏都是人们在信息传播中普遍关注的重大问题。最古老的文件加密手段莫过于对称加密,什么是对称加密,打个比方,有一个商人需要给合作伙伴送一批贵重的货物,他便将货物放在一个设置好密码的箱子中,这个密码只有商人知道,同时他又将设置好的密码提前告知合作伙伴,货物送达后,合作伙伴便可以用被告知的密码打开箱子取出货物。即用一种方法加密, 用同一种方法解密, 即为对称加密。对称加密从古至今都是比较广泛使用的一种加密方式,比如在宋朝就将代码法用于军事保密文件的传输,简而言之,比如双方约定某一本书,根据书中的字所在位子,比如“20页第2行第9个字”,破译的时候只要对照好,就能解码。如果不知道双方约定的解码书本,根本无法破解。这种方式现在还管用。比如在谍战片中,情报人员发出的电报,需要用对应的密码本来解译,如何密码本落入到地方手中,后果不堪设想。但是对称加密缺点在于,通过对称加密方法进行加密后,需要告知接收方加密方法才能解密,而将加密方法传输给接受方这一过程中,充满了各种泄密的可能。比如说在战争中,一旦密码本在传输的过程中被敌方截获,那么所有的电报内容都会被地方破解,以至于影响最终战争胜利的走向。所以,对称加密的安全性,最首先取决于加密方式的保密性,其次才是密码破译的难度。 如何能够消除了对称加密中用户交换密钥的需要的同时也能保证其保密性?因此,诞生的非对称加密。非对称加密算法需要两个密钥:公开密钥 (publickey:简称公钥) 和 私有密钥 (privatekey:简称私钥). 公钥与私钥是一 一对应的, 如果用公钥对数据进行加密, 只有用对应的私钥才能解密. 因为加密和解密使用的是两个不同的密钥, 所以这种算法叫作非对称加密算法. 基本过程为:甲方生成一对密钥与公钥, 并将公钥公开, 需要向甲方发送信息的其他角色(乙方, 丙方等) 使用甲方公开的公钥对机密信息进行加密后再发送给甲方. 甲方再用自己私钥对加密后的信息进行解密.甲方想要回复乙方时正好相反, 使用乙方公开的公钥对数据进行加密,同理,乙方使用自己的私钥来进行解密.本文中介绍非对称加密算法中的一种------RSA加密解密算法。

原文链接:https://blog.csdn.net/qq_43353709/article/details/132282754

设计需求

在QT端实现对字符串的加密与解密

前期准备

OpenSSL工具下载

本人采用Win64OpenSSL-1_1_1t.msi,百度网盘下载链接如下:

链接:https://pan.baidu.com/s/1vg4s_1JmCpa68TMc1F2gMw
提取码:u4js

安装可以参考大神的博文 OpenSSL安装参考链接,很详细,这边就不进行重复介绍。

OpenSSL工具使用

OpenSSL工具使用学习,可以参考大神的博客OpenSS使用参考链接。

完成了前期准备,接下来我们开始QT端的OpenSSL使用

QT端需求实现

pro文件加库

INCLUDEPATH += $$PWD/openssl/
win32 {
#    LIBS += -lwsock32
    LIBS += -L$$PWD/lib/ -llibeay32 -lssleay32
}

动态链接库下载

可以从百度网盘下载,也可以直接在博文资源中下载,已经上传共享。

链接:https://pan.baidu.com/s/1mtmfps7Ob6oMfR0EwmwPSQ
提取码:ux57

主函数实现

公钥实现对字符串“123456”的加密,然后对加密的内容用私钥进行解密

#include <QApplication>
#include "rsa.h"
#include "QDebug"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
//    MainWindow w;
//    w.show();

    QString strPlainData_before = "123456";
               QString strPubKey = "-----BEGIN PUBLIC KEY-----\n"\
                       "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCjBAChJDE8yhBSwsNmRzfDHoVo\n"\
                       "FIFjWICaXfwUU5HGyYnW3AgKnX+itPfWNNXnD4fjOoQv+5VlRUvHgeuFB07yngEG\n"\
                       "AH7WhCllPq1TvQWynQOqdx1Jx7H9w4YyW3IAASSHqQHzAMqSYy1zghcxjyI7NpXP\n"\
                       "A7iMmZ8U0GhgUjcd9wIDAQAB\n"\
                       "-----END PUBLIC KEY-----";
               QString strPriKey = "-----BEGIN RSA PRIVATE KEY-----\n"\
                       "MIICXAIBAAKBgQCjBAChJDE8yhBSwsNmRzfDHoVoFIFjWICaXfwUU5HGyYnW3AgK\n"\
                       "nX+itPfWNNXnD4fjOoQv+5VlRUvHgeuFB07yngEGAH7WhCllPq1TvQWynQOqdx1J\n"\
                       "x7H9w4YyW3IAASSHqQHzAMqSYy1zghcxjyI7NpXPA7iMmZ8U0GhgUjcd9wIDAQAB\n"\
                       "AoGAf4kdGPUg1Gdd9/HKP9WOCchyJOiOBfRywNKw6hIrpbN9dKy2Wd+4wMoGb/7s\n"\
                       "LpbXAG6Chqu0yQM68z5wzaXXG/fPvUOvNcAxKpnSeK/guzNETwxoSRe5duc2o+iY\n"\
                       "m1qG7l6/tYsGZ/qzDHeNateMM4OpC4CobjOlKycpw7N6z6kCQQDQGOATh8B5UcG7\n"\
                       "ViWZ37Yc0K64BK1MwaoS+R33BUWY+UAL5x/im5NmEHVwBSqThyKBReaZxAfGtA0i\n"\
                       "1+AmITorAkEAyIp7N4gP7dbPmanR4dB/ca/y2b8YrFDKjolwceIJQPp/8zEPv28V\n"\
                       "q7032u37UIytQI0CiwnPJw0gnFwBliMBZQJAKeG3x3Z88G3Z9eBCtRNnTalaYMLg\n"\
                       "NiCMIEFvHHY9KaqQj1S3AB6breEGIcOIbCS4dxggbzYa8ozuT+Luw/3P/QJBAK5c\n"\
                       "6aFw5hivizVaGCi09fpNN2Pn6XX5kQS5r1D1bYJXy2QRplWWKkt2a9gozzhL+F+F\n"\
                       "u05Uqw6TNWV+AcseiJkCQE/LuxFAbIdmXLRDLZ9F8q6YB0sJJ/Xq0JqhHwusrEy9\n"\
                       "sYzz9JVuLDZHDsmd8zlm593IVZYmz2Mj4Qqw+KZ0PF4=\n"\
                       "-----END RSA PRIVATE KEY-----";
               QString strEncryptData ;
               QString strPlainData ;

               rsa* m_rsa=new rsa();
               //加密
               strEncryptData = m_rsa->rsaPubEncrypt(strPlainData_before,strPubKey);
qDebug()<<strPlainData_before;
               qDebug()<<strEncryptData;
               //解密
               strPlainData = m_rsa->rsaPriDecrypt(strEncryptData, strPriKey);
qDebug()<<strPlainData;

    return a.exec();
}

加密解密的函数

rsa.h

#ifndef RSA_H
#define RSA_H

#include <QString>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>

#define BEGIN_RSA_PUBLIC_KEY  "BEGIN RSA PUBLIC KEY"
#define BEGIN_RSA_PRIVATE_KEY  "BEGIN RSA PRIVATE KEY"
#define BEGIN_PUBLIC_KEY      "BEGIN PUBLIC KEY"
#define BEGIN_PRIVATE_KEY      "BEGIN PRIVATE KEY"
#define KEY_LENGTH            1024

class rsa
{
public:
    rsa();
    ~rsa();

    bool createRSAKey(QString &strPubKey, QString &strPriKey);


    QString rsaPubEncrypt(const QString &strPlainData, const QString &strPubKey);

    QString rsaPriDecrypt(const QString &strDecryptData, const QString &strPriKey);


};

#endif // RSA_H

rsa.cpp

#include <QDebug>
#include "rsa.h"

#define myDebugMsg(msg) qDebug()<<QString("[Debug] File:%1     Line:%2     Function:%3     Msg:%4").arg(__FILE__).arg(__LINE__).arg(__FUNCTION__).arg(msg)
#define myDebug qDebug()<<QString("[Debug] File:%1     Line:%2     Function:%3").arg(__FILE__).arg(__LINE__).arg(__FUNCTION__)


rsa::rsa()
{

}

rsa::~rsa()
{

}

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;
}


//公钥加密
QString rsa::rsaPubEncrypt(const QString &strPlainData, 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 plainDataArry = strPlainData.toUtf8();
    int nPlainDataLen = plainDataArry.length();
    uchar* pPlainData = (uchar*)plainDataArry.data();
    int nSize = RSA_public_encrypt(nPlainDataLen,
                                   pPlainData,
                                   (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;
}

//私钥解密
QString rsa::rsaPriDecrypt(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* pPlainBuf = new char[nLen];
    memset(pPlainBuf, 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*)pPlainBuf,
                                    pRsa,
                                    RSA_PKCS1_PADDING);

    QString strPlainData = "";
    if (nSize >= 0) {
        strPlainData = QByteArray(pPlainBuf, nSize);
    }

    //释放内存
    delete pPlainBuf;
    BIO_free_all(pKeyBio);
    RSA_free(pRsa);

    return strPlainData;
}


输出图片展示
在这里插入图片描述

Chapter3 Qt —windows和linux下调用Openssl库实现RSA算法

原文链接:https://blog.csdn.net/sunny_hu92/article/details/111270894

一.摘要

最近项目中,需要用到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版,需要开发版本。

Openssl官网

Win32OpenSSL-1_0_2e.exe

然后,按照安装步骤装好后,将安装目录下的lib/MinGW和include文件夹copy到Qt工程目录下;

lib/MinGW一览:
在这里插入图片描述

include文件夹如下:

在这里插入图片描述

1.2 配置Qt工程的.pro文件,加入Windows下依赖的Openssl库和头文件
INCLUDEPATH += P W D / i n c l u d e L I B S + = − L PWD/include LIBS += -L PWD/includeLIBS+=LPWD/lib/MinGW -lssleay32
LIBS += -L$$PWD/lib/MinGW -llibeay32
如此,windows下Openssl库可以正常使用。

2. Linux下

2.1 下载Openssl源码包
openssl-1.0.2e.tar.gz

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++使用

Chapter4 OpenSSL C++ RSA 超长string 加密解密

原文链接:https://blog.csdn.net/begonia__z/article/details/108336245

最近公司为了dll的加密需要服务器生成授权证书文件,因此需要针对授权文件进行RSA加密。RSA的加密的长度是有要求的,因此对于超长的字符串要么采用新的加密方式:

1、AES针对授权证书加密 + RSA针对Key的加密(对称加密是不收到明文长度影响)

2、RSA超长明文分段加密的方式

这里就介绍RSA超长明文分段加密的简单步:

1、根据生成的RSA生成的长度来分割明文字段长度,加密次数 = 明文长度 / RSA加密字段长度 + 1

2、加密后的Base64字段拼接起来,再通过base64 to string 转成可见密文

直接上代码:

//rsa.h
//公钥加解密
static std::string encrypt_RSA_by_long_str_public_key(std::string publicKey, 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 std::string decrypt_RSA_by_long_str_private_key(std::string privateKey, const std::string& data);
Cpp代码:

/*
 * 公钥加密
 */
std::string CRSA::encrypt_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(), true);
 
	int len = RSA_size(rsa);
 
	char* decryptedText = (char*)malloc(len + 1);
	memset(decryptedText, 0, len + 1);
	
	int nClearDataLen = data.length();
 
	int pdBlock = len - 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_public_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;
}
/*
 * 公钥解密
 */
std::string CRSA::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(), true);
 
	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 CRSA::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(), false);
 
	int len = RSA_size(rsa);
 
	char* decryptedText = (char*)malloc(len + 1);
	memset(decryptedText, 0, len + 1);
 
	int nClearDataLen = data.length();
 
	int pdBlock = len - 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;
}
/*
 * 私钥解密
 */
std::string CRSA::decrypt_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(), false);
 
	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_private_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;
}

Chapter5 QT适配OpenSSL库的保姆级教程

原文链接:https://blog.csdn.net/qq_42964109/article/details/136439910

操作步骤

1.查看自己的QT支持的OpenSSL版本号

1.1查看版本号
1.新建项目:OpenSSLDemo[采用MinGw32]进行编译

2.在pro文件中加入QT += network

3.在头文件中加入#include #include

4.qDebug()<<QSslSocket::sslLibraryBuildVersionString();
通过上述步骤:得出支持的OpenSSL版本-----》本人采用的QT版本为:QT5.14.2

在这里插入图片描述

1.2查看自己的QT版本是否配置了OpenSSL

添加头文件 #include <QNetworkAccessManager>
//看看是否配置了ssl
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
qDebug() << manager->supportedSchemes();

通过上述步骤:得出结论未安装OpenSSL

在这里插入图片描述

2 安装OPenSSL

    安装Open SSL的方式有两种:

    1.下载已经编译好的库,放到指定位置

    2.自己编译源码

2.1下载已经编号好的库

网址:
https://slproweb.com/products/Win32OpenSSL.html

在上述网址中找到对应的OPenSSL版本;我的版本是“OpenSSL 1.1.1d 10 Sep 2019” 见官网找到的截图如下:
在这里插入图片描述

一个是OpenSSL库,一个是安装库的必备软件,后面有说明【两个都安装吧】

注意值得提醒的是:

此处有Win32和Win64可选,这里的位数指的是你调用OpenSSL开发出来的软件的位数版本,而不是你计算机的位数。
开发32位软件选择Win32,64位选择Win64,如果同时需要开发32位和64位的则下载两个

比较好的参考网址:
https://blog.csdn.net/zhizhengguan/article/details/112848095
安装过程省略了,直接下一步即可。
有个小插曲----》我把32和64位的都进行了安装。然后再次运行程序以后发现

“OpenSSL 1.1.1d 10 Sep 2019”
(“ftp”, “file”, “qrc”, “http”, “https”, “data”)
输出当前QT支持的openSSL版本: “OpenSSL 1.1.1d 10 Sep 2019”
OpenSSL支持情况: true
OpenSSL运行时SSL库版本: “OpenSSL 1.1.1d 10 Sep 2019”

多出来了https 和支持情况为 true

但是 在网上寻到代码进行 具体功能验证的时候 会报一些奇奇怪怪的错误。一些明明.h文件里有的函数但是不能被找到使用,未定义。

在此呢 先做一个暂定 后续 配置完成在继续教程

在这里插入图片描述

2.2代码进行自我编译:先略过
个人认为没必要,根据QT适配的版本进行下载即可【有闲暇时余再更此段】

3.针对OpenSSL的一些小知识积累

    1.关于名字的变化

在1.0.x之前的版本中,文件为libeay32.dll和ssleay32.dll,在1.1.x之后的版本中,名字是libssl.dll和libcrypto.dll
2.针对于前面造成的问题趟坑后的解决方式
在这里插入图片描述

按照上面的安装OpenSSL 方式.然后将需要的 *.lib 和include文件夹 复制到工程文件夹下面然后在.pro文件里面添加

INCLUDEPATH +=
PWD/includeLIBS+=−L

PWD/lib/MinGW -llibcrypto
LIBS += -L$$PWD/lib/MinGW -llibssl

在这里插入图片描述

上述的操作LIBS 的路径不正确 找到的两个库不对

INCLUDEPATH += $$PWD/include
LIBS += -L$$PWD/lib/ -llibcrypto
LIBS += -L$$PWD/lib/ -llibssl

为了防止有文件被遗忘:建议规范操作-----》将安装路径下的所有文件全部拷贝到工程文件当中

在这里插入图片描述

然后规定只能在pro 里面添加 以下几句话

LIBS += -L$$PWD/OpenSSL_Win32/lib/ -llibssl
LIBS += -L$$PWD/OpenSSL_Win32/lib/ -llibcrypto
 
INCLUDEPATH += $$PWD/OpenSSL_Win32/include
DEPENDPATH += $$PWD/OpenSSL_Win32/include

测试成功的代码如下:

QT -= gui
 
CONFIG += c++11 console
CONFIG -= app_bundle
 
 
DEFINES += QT_DEPRECATED_WARNINGS
 
#INCLUDEPATH += D:\OpenSSL\SSL_32\OpenSSL-Win32\include
 
#LIBS    += D:\OpenSSL\SSL_32\OpenSSL-Win32\lib\libssl.lib \
#           D:\OpenSSL\SSL_32\OpenSSL-Win32\lib\libcrypto.lib
 
 
 
SOURCES += \
        applink.c \# 第二个例子需要
        main.cpp
 
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
 
LIBS += -L$$PWD/OpenSSL-Win32/lib/ -llibssl
 
 
LIBS += -L$$PWD/OpenSSL-Win32/lib/ -llibcrypto
 
 
INCLUDEPATH += $$PWD/OpenSSL-Win32/include
DEPENDPATH += $$PWD/OpenSSL-Win32/include
 
 

==================================================================================
 

#include <QCoreApplication>
#include <openssl/ssl.h>
#include <QDebug>
 
std::string sha256(const std::string str)
{
    char buf[2];
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    SHA256_Update(&sha256, str.c_str(), str.size());
    SHA256_Final(hash, &sha256);
    std::string newString = "";
    for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
    {
        sprintf(buf,"%02x",hash[i]);
        newString = newString + buf;
    }
    return newString;
}
 
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
 
    std::string str = "Hello World";
    qDebug() << QString::fromStdString(sha256(str));
 
//第二个例子
    RSA *rsa = RSA_new();
    SSL_library_init();
    OpenSSL_add_ssl_algorithms();
    SSLeay_add_ssl_algorithms();
    // 生成 RSA 密钥对,这里的 2048 是密钥位数
    BIGNUM *e = BN_new();
    BN_set_word(e, RSA_F4); // RSA_F4 是通常的公钥指数值
    RSA_generate_key_ex(rsa, 2048, e, nullptr);
    
    // 导出公钥到文件
    FILE *pubKeyFile = fopen("public_key.pem", "wb");
    PEM_write_RSAPublicKey(pubKeyFile, rsa);
    
    // 导出私钥到文件(通常需要密码保护)
    FILE *privKeyFile = fopen("private_key.pem", "wb");
    PEM_write_RSAPrivateKey(privKeyFile, rsa, nullptr, nullptr, 0, nullptr, nullptr);
    
    // 释放资源
    RSA_free(rsa);
    BN_free(e);
    fclose(pubKeyFile);
    fclose(privKeyFile);
    
    qDebug()<<"RSA密钥对生成成功!" <<endl;
 
    return a.exec();
}

在第二个例子中 会报错 【OPENSSL_Uplink(59129348,08): no OPENSSL_Applink 】

需要将lib文件夹的applink.c 添加到工程文件夹中
参考:【https://blog.csdn.net/u010058695/article/details/122980941】

特别感谢C/C++编程:openssl使用(win10+qt + qmake)_qt把openssl放到c编译-CSDN博客

OpeSSL 版本众多—需要仔细找到对应的版本进行修改才行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值