基于openssl1.1.1d库的RSA加密解密验证签名(C++版)

编程

1.下载openssl-1.1.1d库以及相关编译依赖
openssl的1.0.x版本和1.1.x版本有细微的不同,本文方法适用于1.1.x版本
openssl库下载路径:https://www.openssl.org/source/
下载其中的openssl-1.1.1d.tar.gz
perl用于配置编译环境,下载路径:https://www.perl.org/get.html#win32
下载其中的:Strawberry Perl
如果在linux上使用,需要注意1.1.x版本中使用函数:secure_getenv 该函数需要glibc版本2.17以上
可以修改源代码使用getenv,该函数说明:http://www.man7.org/linux/man-pages/man3/getenv.3.html
glibc版本下载:http://www.gnu.org/software/libc/

2.安装好perl,解压好openssl后
其中生成makefile的编译选项有:perl Configure { VC-WIN32 | VC-WIN64A | VC-WIN64I | VC-CE } [no-shared][no-asm][no-tests][--debug]
如果编译32位版本:perl Configure VC-WIN32 no-asm no-tests 即可,如果不加no-asm需要安装NASM并且添加路径到Path中
生成makefile后只需要nmake即可。

perl Configure VC-WIN32 no-asm no-tests
nmake

将openssl目录下的include和[libcrypto.lib libssl.lib libssl-1_1.dll libcrypto-1_1.dll]或者[libcrypto_static.lib libssl_static.lib]
添加到自己的工程,注意还需要额外链接ws2_32.lib。

3.代码及其说明如下:

#include "openssl/pem.h"
#include "openssl/ssl.h"
#include "openssl/evp.h"
#include "openssl/sha.h"
#include "openssl/bio.h"
#include "openssl/rsa.h"
#include "openssl/err.h"
#include <string>
#include <iostream>
#include <cstdlib>

#include <atlenc.h> //用于调用 Base64Encode

using namespace std;

int main(int argc, char *argv[])
{
    string strPrivateKey =
        "-----BEGIN RSA PRIVATE KEY-----

"
        "MIICXgIBAAKBgQDIOkm7kTU6m8ALDqPE2nn049vOHSKkekpdzwcOmfYiAwg+sbli"
        "2ToVTlUwM51SDNdOfbvogbH4KeDqwYnb0bjMhk4wxfZPD1wHXotRc/ERN2iaZ6Km"
        "0ImJjlW41zDFicNoj9qre3NpFkAAjXyJEDEdQrVCGYRYvcAYwUtpNVhavwIDAQAB"
        "AoGBAMWSnobyte9rGIjQnVD1tDmtTYuIvFJISXFfg7souPK+wzf57tBXQTUc4np5"
        "s9buzNWqw+ydbZtO151N9FZwD0Qij7YtfvoxNrEzMRd1SzaFMxKOZqNSV8uW6v7o"
        "8ISS7E7YIrnGvJIXTRAOiehu3Zy3maQc6wVLJVDDf0kqHPRhAkEA6VShkeUXxJ9t"
        "08O+YEX+CV3KHXBfmXBIMKaKBAShnVUyx2+TW0C0ZyGTJMwjPhpVIhWDlNwQ1mVT"
        "sMjc+CBWlQJBANuuU2ABCLyyG423PQmOHSuAm+80kUEoPkBpWDOHa+kR7yR1mdaK"
        "ne4Yzv/7aTC9qmKQ+LdtSassGu7YWoM3OwMCQAm+mBTQvYJfqiWK6jt5ENfxS8yY"
        "8dUlpE4r1l2+l8VLVpiPp1bLR/16oHuL7vjb/qwyu9EOs8FQcANVEC1opFUCQQDT"
        "ajZk+znMV2A7B3CfZHxgJFptX9q2qSMX3An9NUO9vvu1y9OsbCTHQmrcYbj/Jlj2"
        "mOwzouK18DFPUTnyc9G/AkEAwyVQYY6tQNUJ6srRA1MrS8K0iwS7PRyt/u+ziBS8"
        "Va/rzRJe9s30pXsiRubUhCCKUvuCWWwOrxhPQB+VGx7EXQ==

"
        "-----END RSA PRIVATE KEY-----

";
    string strPublicKey =
        "-----BEGIN PUBLIC KEY-----

"
        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIOkm7kTU6m8ALDqPE2nn049vO"
        "HSKkekpdzwcOmfYiAwg+sbli2ToVTlUwM51SDNdOfbvogbH4KeDqwYnb0bjMhk4w"
        "xfZPD1wHXotRc/ERN2iaZ6Km0ImJjlW41zDFicNoj9qre3NpFkAAjXyJEDEdQrVC"
        "GYRYvcAYwUtpNVhavwIDAQAB

"
        "-----END PUBLIC KEY-----

";

    //用于测试的明文
    string strText = "Hello,World! p1=3344&p2=12.03&p3=ssaabb";

    //先测试一个错误输出!,这里使用PublicKey去生成PrivateRSA,会生成失败产生一个错误!
    //错误字符串:error:0909006C:PEM routines:get_name:no start line
    //这个一般都是函数用错了,或者Key的格式有问题
    RSA *err_rsa = 0;
    BIO *err_bio = 0;
    err_bio = BIO_new_mem_buf(strPublicKey.c_str(), strPublicKey.size());
    err_rsa = PEM_read_bio_RSAPrivateKey(err_bio, &err_rsa, 0, 0);
    if (!err_rsa)
    {
        int ierr = ERR_get_error();
        char szErr[2048];
        memset(szErr, 0, sizeof(szErr));
        ERR_error_string_n(ierr, szErr, 2048);
        cout << "Test-Error" << endl;
        cout << "err-id:" << ierr << endl;
        cout << "errstr:" << szErr << endl << endl;

        BIO_free(err_bio);
    }

    //这里先生成正确的公钥RSA对象,私钥RSA对象
    RSA *pri_rsa = 0;
    BIO *pri_bio = 0;
    pri_bio = BIO_new_mem_buf(strPrivateKey.c_str(), strPrivateKey.size());
    pri_rsa = PEM_read_bio_RSAPrivateKey(pri_bio, &pri_rsa, 0, 0);

    RSA *pub_rsa = 0;
    BIO *pub_bio = 0;
    pub_bio = BIO_new_mem_buf(strPublicKey.c_str(), strPublicKey.size());
    //pub_rsa = PEM_read_bio_RSAPublicKey(pub_bio, &pub_rsa, 0, 0); //这里不知道为什么不能使用该函数
    pub_rsa = PEM_read_bio_RSA_PUBKEY(pub_bio, &pub_rsa, 0, 0);

    char szCipher[4096]; //密文缓存
    char szPlain[4096]; //明文缓存
    int iLenCipher = 0;
    int iLenPlain = 0;

    char szB64Temp[4096]; //用于base64缓存
    int iLenB64 = 0;

    //输出未加密前的明文,用于对比
    cout << "Test-Plain:

" << strText << endl << endl;

    //测试:私钥加密,公钥解密
    memset(szCipher, 0, sizeof(szCipher));
    memset(szPlain, 0, sizeof(szPlain));
    iLenCipher = RSA_private_encrypt(strText.size(), (const unsigned char*)strText.c_str(), (unsigned char*)szCipher, pri_rsa, RSA_PKCS1_PADDING);
    iLenPlain = RSA_public_decrypt(iLenCipher, (const unsigned char*)szCipher, (unsigned char*)szPlain, pub_rsa, RSA_PKCS1_PADDING);
    //注意,一般加密后都是乱码,实际应用程序中传送的都是base64之后的数据,这里直接输出乱码!
    cout << "private-encrypt:

" << szCipher << endl;
    cout << "public-decrypt:

" << szPlain << endl;
    //输出base64之后的密文
    memset(szB64Temp, 0, sizeof(szB64Temp));
    iLenB64 = 4096;
    Base64Encode((const BYTE*)szCipher, iLenCipher, szB64Temp, &iLenB64);
    cout << "b64-cipher:

" << szB64Temp << endl << endl;

    //测试:公钥加密,私钥解密
    memset(szCipher, 0, sizeof(szCipher));
    memset(szPlain, 0, sizeof(szPlain));
    iLenCipher = RSA_public_encrypt(strText.size(), (const unsigned char*)strText.c_str(), (unsigned char*)szCipher, pub_rsa, RSA_PKCS1_PADDING);
    iLenPlain = RSA_private_decrypt(iLenCipher, (const unsigned char*)szCipher, (unsigned char*)szPlain, pri_rsa, RSA_PKCS1_PADDING);
    //注意RSA算法,公钥加密相同的文本每次密文都会改变,这是正确的,说明RSA难以破解
    cout << "public-encrypt:

" << szCipher << endl;
    cout << "private-decrypt:

" << szPlain << endl;
    memset(szB64Temp, 0, sizeof(szB64Temp));
    iLenB64 = 4096;
    Base64Encode((const BYTE*)szCipher, iLenCipher, szB64Temp, &iLenB64);
    cout << "b64-cipher:

" << szB64Temp << endl << endl;

    //测试:私钥签名,公钥验签
    char szSigned[4096];
    memset(szSigned, 0, sizeof(szSigned));
    int iLenSign = 0;
    RSA_sign(NID_sha1, (const unsigned char*)strText.c_str(), strText.size(), (unsigned char*)szSigned, (unsigned int*)&iLenSign, pri_rsa);
    cout << "private-signed:

" << szSigned << endl;
    int iRet = RSA_verify(NID_sha1, (const unsigned char*)strText.c_str(), strText.size(), (const unsigned char*)szSigned, iLenSign, pub_rsa);
    cout << "public-verify:" << iRet << endl; //1-验签成功,0-验签失败

    RSA_free(pub_rsa);
    BIO_free(pub_bio);
    RSA_free(pri_rsa);
    BIO_free(pri_bio);

    cout << endl << endl;
    system("pause");
    return 0;
}

 

 

 4.运行结果如下:

以上是 基于openssl1.1.1d库的RSA加密解密验证签名(C++版) 的全部内容, 来源链接: utcz.com/z/512344.html

回到顶部