openssl: 多用途的命令行工具,包openssl,可以执行交互或批量命令。
libcrypto: 加密算法库,包openssl-libs。
libssl:加密模块应用库,实现了ssl及tls,包nss。
OpenSSL一共提供了8种对称加密算法,其中7种是分组加密算法,仅有的一种流加密算法是RC4。
这7种分组加密算法分别是AES、DES、Blowfish、CAST、IDEA、RC2、RC5,
都支持电子密码本模式(ECB)、加密分组链接模式(CBC)、加密反馈模式(CFB)和输出反馈模式(OFB)四种常用的分组密码加密模式。其中,AES使用的加密反馈模式(CFB)和输出反馈模式(OFB)分组长度是128位,其它算法使用的则是64位。事实上,DES算法里面不仅仅是常用的DES算法,还支持三个密钥和两个密钥3DES算法。
OpenSSL v1.1.0f
下载地址:https://slproweb.com/products/Win32OpenSSL.html)
【提醒事项】
1。安装OpenSSL有两种方法,第一种为下载OpenSSL源代码并由自己编译后使用;第二种为下载已编译好的安装包,安装后直接可以使用。因第一种方法十分繁琐,需要安装Ruby进行编译,同时编译过程中可能产生各种各种的问题,因此在此采用第二种方法
2。每次新建工程之后都要配置一下OpenSSL开发环境
3。本人用的英文环境(英文操作系统+英文软件),因此操作界面语言可能会和中文环境有些不同,但并不影响功能
【具体步骤】
1。下载编译好的OpenSSL安装包(下载地址见上方),此处有Win32和Win64可选,这里的位数指的是你调用OpenSSL开发出来的软件的位数版本,而不是你计算机的位数。开发32位软件选择Win32,64位选择Win64,如果同时需要开发32位和64位的则下载两个。确定好位数后,下载Win32/64 OpenSSL v1.1.0f(版本号可能会因更新而有所不同),“Light版”为“轻量版”,即只包含了核心功能的版本,本文演示的为“非Light版”
2。下载完后打开安装,选择安装位置,64位和32位不要安装在同一个目录下
3。选择把dll复制到OpenSSL目录下(主要是为了以后好找,如果选择复制到Windows系统目录下,天知道复制到哪里去了。。。)
4。安装完成后,如果有捐款意向的可以捐款(别误会我不是在打广告。。。即使你捐款了我也拿不到一分钱),没有意向则取消掉钩,然后点“Finish”
5。新建一个解决方案,方便起见,这里新建一个控制台应用程序,这里我没有勾选“Create directory for solution”是因为这是一个单项目解决方案,所以我觉得没有必要多创建一层文件夹
6。勾选“Empty project”(这个是个人习惯,可能钩不钩并没有什么影响(“可能”这个词就很骚了。。。))
7。右击工程,选择“Properties”
8。点击左方的“VC++ Directories”,然后左上角选择“All Configurations”
9。右上角选择平台,这里演示x64的,如果是开发Win32软件就选Win32,如果要Win64和Win32兼顾,则分别配置一下(就是先选择Win32进行配置,然后再选择x64进行配置)
10。选中“Include Directories”,点击右边的下拉按钮,点击“Edit…”
11。点击右上方的“New Line”按钮,然后点击新行右边的“…”按钮
12。在弹出的目录选择界面中选择OpenSSL安装目录下的“include”文件夹,点击“Select Folder”,再点击“OK”完成添加
13。同样的方法,将安装目录下的“lib”文件夹添加到“Library Directories”中
14。将OpenSSL安装目录下bin文件夹中的“libcrypto-1_1-x64.dll”和“libssl-1_1-x64.dll”(名字后面的版本号可能因更新而不同)复制到工程目录下
15。将工程平台调整为自己需要的平台,这里演示x64平台
16。添加lib文件,这里有A、B两种方法,分别列出:
16-A:
在代码中添加
?
1 2 |
|
16-B:
在“Property Pages->Linker->Input->Additional Dependencies”添加libssl.lib和libcrypto.lib
#include
#include
#include
#include
#include
char * base64Encode(const char *buffer, int length, bool newLine);
char * base64Decode(const char *input, int length, bool newLine);
// 私钥解密
std::string rsa_pri_decrypt(const std::string &cipherText, const std::string &priKey)
{
std::string strRet;
RSA *rsa = RSA_new();
BIO *keybio;
keybio = BIO_new_mem_buf((unsigned char *)priKey.c_str(), -1);
// 此处有三种方法
// 1, 读取内存里生成的密钥对,再从内存生成rsa
// 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa
// 3,直接从读取文件指针生成rsa
rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);
int len = RSA_size(rsa);
char *decryptedText = (char *)malloc(len + 1);
memset(decryptedText, 0, len + 1);
// 解密函数
int ret = RSA_private_decrypt(cipherText.length(), (const unsigned char*)cipherText.c_str(), (unsigned char*)decryptedText, rsa, RSA_PKCS1_PADDING);
if (ret >= 0)
strRet = std::string(decryptedText, ret);
// 释放内存
free(decryptedText);
BIO_free_all(keybio);
RSA_free(rsa);
return strRet;
}
// 公钥解密
std::string rsa_pub_decrypt(const std::string &cipherText, const std::string &pubKey)
{
std::string strRet;
RSA *rsa = RSA_new();
BIO *keybio = BIO_new_mem_buf((unsigned char *)pubKey.c_str(), -1);
rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
int len = RSA_size(rsa);
char *decryptedText = (char *)malloc(len + 1);
memset(decryptedText, 0, len + 1);
// 解密函数
int ret = RSA_public_decrypt(cipherText.length(), (const unsigned char*)cipherText.c_str(), (unsigned char*)decryptedText, rsa, RSA_PKCS1_PADDING);
if (ret >= 0)
strRet = std::string(decryptedText, ret);
// 释放内存
free(decryptedText);
BIO_free_all(keybio);
RSA_free(rsa);
return strRet;
}
// base64 编码
char * base64Encode(const char *buffer, int length, bool newLine)
{
BIO *bmem = NULL;
BIO *b64 = NULL;
BUF_MEM *bptr;
b64 = BIO_new(BIO_f_base64());
if (!newLine) {
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
}
bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
BIO_write(b64, buffer, length);
BIO_flush(b64);
BIO_get_mem_ptr(b64, &bptr);
BIO_set_close(b64, BIO_NOCLOSE);
char *buff = (char *)malloc(bptr->length + 1);
memcpy(buff, bptr->data, bptr->length);
buff[bptr->length] = 0;
BIO_free_all(b64);
return buff;
}
// base64 解码
char * base64Decode(const char *input, int length, bool newLine)
{
BIO *b64 = NULL;
BIO *bmem = NULL;
char *buffer = (char *)malloc(length);
memset(buffer, 0, length);
b64 = BIO_new(BIO_f_base64());
if (!newLine) {
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
}
bmem = BIO_new_mem_buf(input, length);
bmem = BIO_push(b64, bmem);
BIO_read(bmem, buffer, length);
BIO_free_all(bmem);
return buffer;
}
int main()
{
std::stringstream pkey;
std::stringstream text;
std::string dtext;
text << "D5T51Gw6ZyAGs2wcjz4Fq9JquET3Umfzub1wn8x1CVpeESuoadUbqq8Ve2FXctB9n6qt9BgamV2M1HbW/G255B8Bb";
text << "x5wyfI+eWF2XRyyQzyZ8/ZnB+iyBFcPk47xZdxAHqA+3mP9fKY4bHj2dOa9bNvLSt+9WW5jUZ1ceIE/+8A=";
//需要注意PKSC#1格式头("-----BEGIN RSA PRIVATE KEY-----\n";"-----END RSA PRIVATE KEY-----\n";)。
//数据注意64位分行,有些库还需注意分段解密,一段一般为128byte。
pkey << "-----BEGIN RSA PRIVATE KEY-----\n";
pkey << "MIICXAIBAAKBgQCkB5lY8kxzgEkUC/dRgpKylGOdG2f9iCjS92USD0SlN2eYUsP6\n";
pkey << "EQjY+l8BUThtmBfdM5+K3aXdNLiZd3zBSRQLwiUhzfKSF35k682jtv7R05RZTNlD\n";
pkey << "2CFDwsExE5kAlByPA6QLpiq56IunKZVyqDCza8GwhzUBzJsyCa8lbp7iyj/I0bxB\n";
pkey << "0vMoKZ6ksTU7lNyriNOBPNnxbBTzRZmR90nBcnLqDQVvYRECQQDOu33RnAFhT+ql\n";
pkey << "xoTIH9yLruXdwPCsmsNY8e8sWFHpmb92qYD7N14Cf9dwTQ4yHRE3oAHdxz3cjBTP\n";
pkey << "Q3jnasffAkEAyx7dK4Cu538QlEwvDdxp4hD6shBL3cmJjTld5F7F95feNYEs5L8o\n";
pkey << "Zi2UeLajeOw8JHtnGC+z8W99YmJyl1mz5wJBALDFg42Db26tbkB4YrvY+rX6RJX8\n";
pkey << "0A9XeqiIn3H0x34POLeXszGco2dRt39QdE4Hqtw8lrv0DYKTyYt871o6ZVMCQAni\n";
pkey << "PZbhUyF2oGLm9h8xi4FxnBFQE7D+HpBdq0Dyj6WFoU1vNLUIzDl0nFXnZTr8G80W\n";
pkey << "qCSYJaRo7Wv9KGBPAB8CQE4Bkid2tj1tfnLkhJUBsilJuVBmeF1NZfxMPueIARqs\n";
pkey << "9bVlL4KnTZuXkiA7p13vL84SVOqAWqV8xZb618KLhFc=\n";
pkey << "-----END RSA PRIVATE KEY-----\n";
//base64需要使用专用的方法
char *base64D = {0};
base64D=base64Decode(text.str().c_str(), text.str().size(),0);
dtext=rsa_pri_decrypt(base64D,pkey.str());
std::cout << dtext << std::endl;
//上面密钥请替换为自己的密钥,本密钥已被破坏
//输出为{"name":"fd","age":"\u5927\u5bb6\u53d1\u7262\u9a9a"}
}