本教程为openssl-1.1.1j.tar.gz为例子
第一步:下载OpenSSL源码
下载地址: https://www.openssl.org/source/
个人网盘: https://pan.ltools.vip/#/s/o8TJ
![kv6h007q.png kv6h007q.png](https://pan.pigeoooon.cool/d/imgs/blog/loading.gif)
选择 openssl-x.x.x?.tar.gz
其中 x.x.x?
为目前最新版本号
解压到任意目录下,后续的目录均用 PATH
代替
第二步:下载安装ActivePerl
下载地址:https://www.activestate.com/activeperl/downloads/
个人网盘: https://pan.ltools.vip/#/s/m4sP
如果这个网址打不开的话,可以直接百度搜索ActivePerl下载。
运行安装程序,一直下一步操作安装完成。这里默认安装在C:\Perl64。
![kv6h158k.png kv6h158k.png](https://pan.pigeoooon.cool/d/imgs/blog/loading.gif)
打开 C:\Perl64\site\lib\ActivePerl\Config.pm
文件,将400行左右的代码注释掉,如下图。
![kv6h27u6.png kv6h27u6.png](https://pan.pigeoooon.cool/d/imgs/blog/loading.gif)
第三步:编译64位版本
1、打开VS2019的 x86_x64 Cross Tools Command Prompt for VS 2019
软件
![kv6h3i09.png kv6h3i09.png](https://pan.pigeoooon.cool/d/imgs/blog/loading.gif)
![kv6h3szh.png kv6h3szh.png](https://pan.pigeoooon.cool/d/imgs/blog/loading.gif)
2、使用 cd /d PATH
到我们的解压目录
3、使用 perl Configure VC-WIN64A no-asm no-shared --prefix="C:\Program Files\openssl_bin"
进行生成编译脚本
4、如果编译不过,出现LNK2019等错误的时候,你可能还需要添加ws2_32.lib,crypt32.lib库。打开我们的 PATH
目录下 makefile
文件,将如下位置 EX_LIBS
后添加 Crypt32.lib Ws2_32.lib
![kv6h5enb.png kv6h5enb.png](https://pan.pigeoooon.cool/d/imgs/blog/loading.gif)
5、使用 nmake
进行编译
6、使用 nmake test
进行测试,出现 Result: PASS
则为成功
7、使用 nmake install
将编译好的文件拷贝到我们设定的目录下 C:\Program Files\openssl_bin
8、使用 nmake clean
清除上次静态库的编译,以便重新编译
第四步:编译32位版本
1、打开VS2019的 x64_x86 Cross Tools Command Prompt for VS 2019
软件
![kv6h6vs7.png kv6h6vs7.png](https://pan.pigeoooon.cool/d/imgs/blog/loading.gif)
![kv6h70i4.png kv6h70i4.png](https://pan.pigeoooon.cool/d/imgs/blog/loading.gif)
2、使用 cd /d PATH
到我们的解压目录
3、使用 perl Configure VC-WIN32 no-asm no-shared --prefix="C:\Program Files (x86)\openssl_bin"
进行生成编译脚本
4、如果编译不过,出现LNK2019等错误的时候,你可能还需要添加ws2_32.lib,crypt32.lib库。打开我们的 PATH
目录下 makefile
文件,将如下位置 EX_LIBS
后添加 Crypt32.lib Ws2_32.lib
5、使用 nmake
进行编译
6、使用 nmake test
进行测试,出现 Result: PASS
则为成功
7、使用 nmake install
将编译好的文件拷贝到我们设定的目录下 C:\Program Files (x86)\openssl_bin
8、使用 nmake clean
清除上次静态库的编译,以便重新编译
第五步:使用openssl库
1、给项目包含目录添加我们编译好的openssl库文件中的 include
目录
2、在使用openssl库函数时,添加如下头文件(按需添加)即可,一下使用RSA为例:
1 2 3 4
| #include <openssl/rsa.h> #include <openssl/engine.h> #include <openssl/pem.h> #include <openssl/err.h>
|
3、将我们编译好的静态文件 libcrypto.lib
和 libssl.lib
添加至我们的项目中
1 2
| #pragma comment(lib, "libssl.lib") #pragma comment(lib, "libcrypto.lib")
|
4、进行编译,若出现如下错误请添加 ws2_32.lib
依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 1>libcrypto.lib(b_sock.obj) : error LNK2019: 无法解析的外部符号 __imp_ioctlsocket,函数 BIO_socket_ioctl 中引用了该符号 1>libcrypto.lib(b_sock.obj) : error LNK2019: 无法解析的外部符号 __imp_getsockname,函数 BIO_sock_info 中引用了该符号 1>libcrypto.lib(b_sock.obj) : error LNK2019: 无法解析的外部符号 __imp_getsockopt,函数 BIO_sock_error 中引用了该符号 1>libcrypto.lib(b_sock2.obj) : error LNK2001: 无法解析的外部符号 __imp_getsockopt 1>libcrypto.lib(b_sock.obj) : error LNK2019: 无法解析的外部符号 __imp_ntohs,函数 BIO_get_port 中引用了该符号 1>libcrypto.lib(b_addr.obj) : error LNK2001: 无法解析的外部符号 __imp_ntohs 1>libcrypto.lib(b_sock.obj) : error LNK2019: 无法解析的外部符号 __imp_gethostbyname,函数 BIO_gethostbyname 中引用了该符号 1>libcrypto.lib(b_sock.obj) : error LNK2019: 无法解析的外部符号 __imp_WSAStartup,函数 BIO_sock_init 中引用了该符号 1>libcrypto.lib(b_sock.obj) : error LNK2019: 无法解析的外部符号 __imp_WSACleanup,函数 bio_sock_cleanup_int 中引用了该符号 1>libcrypto.lib(b_sock.obj) : error LNK2019: 无法解析的外部符号 __imp_WSAGetLastError,函数 BIO_accept 中引用了该符号 1>libcrypto.lib(bss_sock.obj) : error LNK2001: 无法解析的外部符号 __imp_WSAGetLastError 1>libcrypto.lib(b_sock2.obj) : error LNK2001: 无法解析的外部符号 __imp_WSAGetLastError 1>libcrypto.lib(b_addr.obj) : error LNK2019: 无法解析的外部符号 __imp_getaddrinfo,函数 BIO_lookup 中引用了该符号 1>libcrypto.lib(b_addr.obj) : error LNK2019: 无法解析的外部符号 __imp_freeaddrinfo,函数 BIO_ADDRINFO_free 中引用了该符号 1>libcrypto.lib(b_addr.obj) : error LNK2019: 无法解析的外部符号 __imp_getnameinfo,函数 addr_strings 中引用了该符号 1>libcrypto.lib(bss_sock.obj) : error LNK2019: 无法解析的外部符号 __imp_recv,函数 sock_read 中引用了该符号 1>libcrypto.lib(bss_sock.obj) : error LNK2019: 无法解析的外部符号 __imp_send,函数 sock_write 中引用了该符号 1>libcrypto.lib(bss_sock.obj) : error LNK2019: 无法解析的外部符号 __imp_WSASetLastError,函数 sock_write 中引用了该符号 1>libcrypto.lib(b_sock2.obj) : error LNK2019: 无法解析的外部符号 __imp_accept,函数 BIO_accept_ex 中引用了该符号 1>libcrypto.lib(b_sock2.obj) : error LNK2019: 无法解析的外部符号 __imp_bind,函数 BIO_bind 中引用了该符号 1>libcrypto.lib(b_sock2.obj) : error LNK2019: 无法解析的外部符号 __imp_closesocket,函数 BIO_accept_ex 中引用了该符号 1>libcrypto.lib(b_sock2.obj) : error LNK2019: 无法解析的外部符号 __imp_connect,函数 BIO_connect 中引用了该符号 1>libcrypto.lib(b_sock2.obj) : error LNK2019: 无法解析的外部符号 __imp_listen,函数 BIO_listen 中引用了该符号 1>libcrypto.lib(b_sock2.obj) : error LNK2019: 无法解析的外部符号 __imp_setsockopt,函数 BIO_connect 中引用了该符号 1>libcrypto.lib(b_sock2.obj) : error LNK2019: 无法解析的外部符号 __imp_socket,函数 BIO_socket 中引用了该符号
|
1
| #pragma comment(lib, "ws2_32.lib")
|
5、若出现如下错误请添加 Crypt32.lib
依赖
1 2 3 4 5 6 7
| 1>libcrypto.lib(e_capi.obj) : error LNK2019: 无法解析的外部符号 __imp_CertOpenStore,函数 capi_list_certs 中引用了该符号 1>libcrypto.lib(e_capi.obj) : error LNK2019: 无法解析的外部符号 __imp_CertCloseStore,函数 capi_find_key 中引用了该符号 1>libcrypto.lib(e_capi.obj) : error LNK2019: 无法解析的外部符号 __imp_CertEnumCertificatesInStore,函数 capi_find_cert 中引用了该符号 1>libcrypto.lib(e_capi.obj) : error LNK2019: 无法解析的外部符号 __imp_CertFindCertificateInStore,函数 capi_find_cert 中引用了该符号 1>libcrypto.lib(e_capi.obj) : error LNK2019: 无法解析的外部符号 __imp_CertDuplicateCertificateContext,函数 capi_load_ssl_client_cert 中引用了该符号 1>libcrypto.lib(e_capi.obj) : error LNK2019: 无法解析的外部符号 __imp_CertFreeCertificateContext,函数 capi_dsa_free 中引用了该符号 1>libcrypto.lib(e_capi.obj) : error LNK2019: 无法解析的外部符号 __imp_CertGetCertificateContextProperty,函数 capi_cert_get_fname 中引用了该符号
|
最后为RSA的完整示例代码
RSA头文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #pragma once
#include <openssl/rsa.h> #include <openssl/engine.h> #include <openssl/pem.h> #include <openssl/err.h> #include <string>
#pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "Crypt32.lib") #pragma comment(lib, "libssl.lib") #pragma comment(lib, "libcrypto.lib")
void CreateRSAPrivateAndPublicKey(int nPrime = 65537, int nKeySize = 2048, std::string strSavePath = "");
std::string RSAPrivateEncrypt(const std::string& strPrivateKey, const std::string& strData);
std::string RSAPrivateDecrypt(const std::string& strPrivateKey, const std::string& strData);
std::string RSAPublicEncrypt(const std::string& strPublicKey, const std::string& strData);
std::string RSAPublicDecrypt(const std::string& strPublicKey, const std::string& strData);
|
RSA源文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
| #include "RSA.h" #include <assert.h>
void CreateRSAPrivateAndPublicKey(int nPrime, int nKeySize, std::string strSavePath) { RSA* rsa = RSA_new(); BIGNUM* e = BN_new(); BN_set_word(e, nPrime); RSA_generate_key_ex(rsa, nKeySize, e, 0);
std::string privatePath = strSavePath + "privateKey.pem"; BIO* _pri = BIO_new_file(privatePath.c_str(), "w"); PEM_write_bio_RSAPrivateKey(_pri, rsa, NULL, NULL, 0, NULL, NULL); std::string publicPath = strSavePath + "publicKey.pem"; BIO* _pub = BIO_new_file(publicPath.c_str(), "w"); PEM_write_bio_RSAPublicKey(_pub, rsa);
BIO_free(_pub); BIO_free(_pri); BN_free(e); RSA_free(rsa); CRYPTO_cleanup_all_ex_data(); }
std::string RSAPrivateEncrypt(const std::string& strPrivateKey, const std::string& strData) { if (strPrivateKey.empty() strData.empty()) { assert(false); return ""; }
RSA* pRSAPrivateKey = RSA_new(); BIO* bio = BIO_new(BIO_s_mem()); BIO_write(bio, strPrivateKey.c_str(), strPrivateKey.size()); pRSAPrivateKey = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL); if (pRSAPrivateKey == nullptr) { assert(false); return ""; }
int nLen = RSA_size(pRSAPrivateKey);
std::string strRet;
char* pEncode = new char[nLen + 1]; int ret = RSA_private_encrypt(strData.length(), (const unsigned char*)strData.c_str(), (unsigned char*)pEncode, pRSAPrivateKey, RSA_PKCS1_PADDING); if (ret >= 0) { strRet = std::string(pEncode, ret); } delete[] pEncode; RSA_free(pRSAPrivateKey); CRYPTO_cleanup_all_ex_data(); return strRet; }
std::string RSAPrivateDecrypt(const std::string& strPrivateKey, const std::string& strData) { if (strPrivateKey.empty() strData.empty()) { assert(false); return ""; }
RSA* pRSAPrivateKey = RSA_new(); BIO* bio = BIO_new(BIO_s_mem()); BIO_write(bio, strPrivateKey.c_str(), strPrivateKey.size()); pRSAPrivateKey = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL); if (pRSAPrivateKey == nullptr) { assert(false); return ""; }
int nLen = RSA_size(pRSAPrivateKey);
std::string strRet;
char* pEncode = new char[nLen + 1]; int ret = RSA_private_decrypt(strData.length(), (const unsigned char*)strData.c_str(), (unsigned char*)pEncode, pRSAPrivateKey, RSA_PKCS1_PADDING); if (ret >= 0) { strRet = std::string(pEncode, ret); } delete[] pEncode; RSA_free(pRSAPrivateKey); CRYPTO_cleanup_all_ex_data(); return strRet; }
std::string RSAPublicEncrypt(const std::string& strPublicKey, const std::string& strData) { if (strPublicKey.empty() strData.empty()) { assert(false); return ""; }
RSA* pRSAPublicKey = RSA_new(); BIO* bio = BIO_new(BIO_s_mem()); BIO_write(bio, strPublicKey.c_str(), strPublicKey.size()); pRSAPublicKey = PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL); if (pRSAPublicKey == nullptr) { assert(false); return ""; }
int nLen = RSA_size(pRSAPublicKey);
std::string strRet;
char* pEncode = new char[nLen + 1]; int ret = RSA_public_encrypt(strData.length(), (const unsigned char*)strData.c_str(), (unsigned char*)pEncode, pRSAPublicKey, RSA_PKCS1_PADDING); if (ret >= 0) { strRet = std::string(pEncode, ret); } delete[] pEncode; RSA_free(pRSAPublicKey); CRYPTO_cleanup_all_ex_data(); return strRet; }
std::string RSAPublicDecrypt(const std::string& strPublicKey, const std::string& strData) { if (strPublicKey.empty() strData.empty()) { assert(false); return ""; }
RSA* pRSAPublicKey = RSA_new(); BIO* bio = BIO_new(BIO_s_mem()); BIO_write(bio, strPublicKey.c_str(), strPublicKey.size()); pRSAPublicKey = PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL); if (pRSAPublicKey == nullptr) { assert(false); return ""; }
int nLen = RSA_size(pRSAPublicKey);
std::string strRet;
char* pEncode = new char[nLen + 1]; int ret = RSA_public_decrypt(strData.length(), (const unsigned char*)strData.c_str(), (unsigned char*)pEncode, pRSAPublicKey, RSA_PKCS1_PADDING); if (ret >= 0) { strRet = std::string(pEncode, ret); } delete[] pEncode; RSA_free(pRSAPublicKey); CRYPTO_cleanup_all_ex_data(); return strRet; }
|
RSA使用实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include <iostream> #include <string> #include "RSA.h"
using namespace std;
string privateKey = "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEA9Bhk806dD+exe+rnBEInMhJ9zaE0Ok/3iscSiT9uI/mKdtj2\nQfQ4QH9yRHbIm+yFaPo+xOd2jVjJcJtDiHFk/4IjuE65OWaI7wryMa5/SP8GijNm\nDpPHNbNVfGrL+qL7+H6tZZ9ggFxgE2bqw97MBAW63DtAzeFeQyleHtxUpwRONazU\nYOhz2CZAqOUSoxwztx8CWtZSCNOV4cs67e7Q/uyuZPIxlS2z2MgI65/ez4vqZkj6\nbJHHb5c7gd4MMbnZ54xWI+S3mtcrOF8SV5ITTtt+tgGygm1kNeasKJRRqKqib2IE\nuRo1taKKr++Q9hSBk95saqcKkovyqinr6v1yCQIDAQABAoIBAQChfwJLd9eyjjh/\nJAt0ZdBI8LMLOXy0l/PPfaZl5/GXG6Lgvusu98W/5pJTecOAZhxeODMPU5S8L+IW\n/qLPwzZvVksLxgoGUDCI91UGSc0tHo3VIeyD+IH0pZIJnx8V1H+hCS7v7WKLipKG\nQ7FPpjiU8LWQwCNAE7up89Sx1lSrqoLMf5oyKbZ42Jld0oFBmljp/EW6Mo7tvQlv\nI5tAYccNHKvVwqYk1VMEU9LBqHDLpJXeRMxlxQTB2cfEr/CaAkCJE2mf5REFgsuB\nJ36AwRfKLcwFDPCv9r850l+AYh5NRlkp3FwIi+s5obpMGUfnCdcQMBmcerwwkTyf\ntoUl892BAoGBAPpkQcIGBiegPncUih9RXvEbNx/lmuqncWTd6DcjMuX2Of2ll32V\n1g4Nc8SzfHl3TZPe0qTN61NqH8ZIubNObz+5C8Fa9k+fSeQIbE5iYx2U+9ZLLmFg\nSq7QcAxprWIm5Bu7r6XWzPJtrIjoJ0JF0T3oxITKnaJiCIDhPoSTpPFrAoGBAPmQ\nCMnj1ccB+K7/ODFbx05MDWONpkjFonrQnBrRXThoRklLRA5DAYsxT5iLS7fJ2mKa\nk13eyJZdtJ1JD6DPuGcai/7ZeGn/l2E8fpNapCPyhQeG1CIbqwa6MGGqfPQjqTQ7\nmWWoEH/lEvwH5yx9hlh8ZKnFUyIHoBV8qvMrjiNbAoGBAKBa4q4SU5C/FCII+mgS\nIZ6Bkm0QC4Vp1LoHT3c4SJlzdjIWAY3BDsQTI2f+lqHnoLwpgHdhFOtn1I+U9bB6\nc864gGnFCmd1mMm8Bziv09AXIK1dmodsNof8HzYj25E3XPDR4yxvAvPi/xLysmnD\n8rwWPPzaEdfztoRrPDGFqKWfAoGBAIHh0HEiPlRAVmjdMyWdGnFJa35wbiZZlWJN\nx7C9XcLJoirrHRQ/E0KZ+07s0A9q4lmHEUM9ey+mvSVOrO+Iq/QdANc131FrUCGv\nFkEiX2LGCS4NocHOnIf3xs5NqJJ3LMyeaAtcGJo3YlYA1vN0sMLEmq8wnz+KsGn+\nZAoClQsZAoGAcsOZnAUfRpdu5H1femhlU83MzpdDNsIcgEp6m0on0i4q/e4n2VgJ\nBXi1/K1tbnU2cU6A4FmLlJ1i9Lf7JAdycylRm5BG9ynXeb3uligxh0kN5SvIiADY\n7MLCB6DyqyXaD7uf903lWJOOlBQpL+aypUAQ5jLyr9zaVDiDwuzPAYU=\n-----END RSA PRIVATE KEY-----"; string publicKey = "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEA9Bhk806dD+exe+rnBEInMhJ9zaE0Ok/3iscSiT9uI/mKdtj2QfQ4\nQH9yRHbIm+yFaPo+xOd2jVjJcJtDiHFk/4IjuE65OWaI7wryMa5/SP8GijNmDpPH\nNbNVfGrL+qL7+H6tZZ9ggFxgE2bqw97MBAW63DtAzeFeQyleHtxUpwRONazUYOhz\n2CZAqOUSoxwztx8CWtZSCNOV4cs67e7Q/uyuZPIxlS2z2MgI65/ez4vqZkj6bJHH\nb5c7gd4MMbnZ54xWI+S3mtcrOF8SV5ITTtt+tgGygm1kNeasKJRRqKqib2IEuRo1\ntaKKr++Q9hSBk95saqcKkovyqinr6v1yCQIDAQAB\n-----END RSA PUBLIC KEY-----";
int main() { std::string strTest = "测试文本"; std::string strRet; strRet = RSAPublicEncrypt(publicKey, strTest); cout << strRet << endl; strRet = RSAPrivateDecrypt(privateKey, strRet); cout << strRet << endl; return 0; }
|
写在最后
上面的我想必你一定学会怎么配置openssl和使用他了,那么再说一个更简单的使用办法就是使用vcpkg可以非常简单的编译并使用openssl库,哈哈哈哈哈哈哈哈哈哈。