好久之前找过一次资料, 然后代码不知道丢哪了, 今天找了大半天才找到怎么生成, 悲剧
发个贴备份一下
下面这段代码可以自己写到一个头文件里, 以后需要加解密就引用他就行
#include <string>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
namespace openssl_rsa_3_x
{
inline void GenerateKeysForEvp(EVP_PKEY* pkey, std::string& pri_key, std::string& pub_key)
{
BIO* pri = BIO_new(BIO_s_mem());
BIO* pub = BIO_new(BIO_s_mem());
PEM_write_bio_PrivateKey(pri, pkey, NULL, NULL, 0, NULL, NULL);
PEM_write_bio_PUBKEY(pub, pkey);
size_t pri_len = BIO_pending(pri);
size_t pub_len = BIO_pending(pub);
pri_key.resize(pri_len);
pub_key.resize(pub_len);
BIO_read(pri, &pri_key[0], pri_len);
BIO_read(pub, &pub_key[0], pub_len);
BIO_free_all(pub);
BIO_free_all(pri);
}
inline bool GenerateKeys1(std::string& pri_key, std::string& pub_key, UINT bits = 2048)
{
EVP_PKEY* pkey = EVP_RSA_gen(bits);
if (!pkey)
return false;
GenerateKeysForEvp(pkey, pri_key, pub_key);
EVP_PKEY_free(pkey);
return true;
}
inline bool GenerateKeys2(std::string& pri_key, std::string& pub_key, UINT bits = 2048)
{
EVP_PKEY* pkey = NULL;
EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
EVP_PKEY_keygen_init(pctx);
EVP_PKEY_generate(pctx, &pkey);
if (!pkey)
return false;
GenerateKeysForEvp(pkey, pri_key, pub_key);
EVP_PKEY_CTX_free(pctx);
return true;
}
inline bool GenerateKeys3(std::string& pri_key, std::string& pub_key, UINT bits = 2048)
{
unsigned int primes = 3;
OSSL_PARAM params[3];
EVP_PKEY* pkey = NULL;
EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
EVP_PKEY_keygen_init(pctx);
params[0] = OSSL_PARAM_construct_uint("bits", &bits);
params[1] = OSSL_PARAM_construct_uint("primes", &primes);
params[2] = OSSL_PARAM_construct_end();
EVP_PKEY_CTX_set_params(pctx, params);
EVP_PKEY_generate(pctx, &pkey);
if (!pkey)
{
EVP_PKEY_CTX_free(pctx);
return false;
}
GenerateKeysForEvp(pkey, pri_key, pub_key);
EVP_PKEY_CTX_free(pctx);
return true;
}
inline std::string rsa_encrypt(LPCVOID pData, size_t nSize, LPCSTR pub_key)
{
std::string en_data;
if (!pData || nSize == 0)
return en_data;
EVP_PKEY_CTX* ctx = 0;
BIO* keybio = BIO_new_mem_buf(pub_key, -1);
EVP_PKEY* pKey = PEM_read_bio_PUBKEY(keybio, 0, NULL, NULL);
while (pKey)
{
ctx = EVP_PKEY_CTX_new(pKey, NULL);
if (!ctx)
break;
if (EVP_PKEY_encrypt_init(ctx) <= 0)
break;
const int key_len = EVP_PKEY_size(pKey);
char* buf = new char[key_len];
LPCBYTE ptr = reinterpret_cast<LPCBYTE>(pData);
LPCBYTE pEnd = ptr + nSize; const int block_len = key_len - 11;
int len = block_len;
const size_t reserve_size = ((nSize / block_len + ((nSize % block_len == 0) ? 0 : 1)) * key_len);
en_data.reserve(reserve_size);
while (ptr < pEnd)
{
if ((ptr + len) > pEnd)
len = pEnd - ptr;
size_t outl = block_len;
int ret = EVP_PKEY_encrypt(ctx, reinterpret_cast<LPBYTE>(buf), &outl, ptr, len);
if (ret > 0)
{
en_data.append(buf, outl);
}
ptr += len;
}
delete[] buf;
break;
}
if (pKey)
EVP_PKEY_free(pKey);
if (ctx)
EVP_PKEY_CTX_free(ctx);
return en_data;
}
inline std::string rsa_decrypt(LPCVOID pData, size_t nSize, LPCSTR pri_key)
{
std::string de_data;
if (!pData || nSize == 0)
return de_data;
EVP_PKEY_CTX* ctx = 0;
BIO* keybio = BIO_new_mem_buf(pri_key, -1);
EVP_PKEY* pKey = PEM_read_bio_PrivateKey(keybio, 0, NULL, NULL);
while (pKey)
{
ctx = EVP_PKEY_CTX_new(pKey, NULL);
if (!ctx)
break;
if (EVP_PKEY_decrypt_init(ctx) <= 0)
break;
de_data.reserve(nSize);
LPCBYTE ptr = reinterpret_cast<LPCBYTE>(pData);
LPCBYTE pEnd = ptr + nSize; const int key_len = EVP_PKEY_size(pKey);
int len = key_len;
char* buf = new char[key_len + 1];
while (ptr < pEnd)
{
if ((ptr + len) > pEnd)
len = pEnd - ptr;
size_t outl = key_len;
int ret = EVP_PKEY_decrypt(ctx, reinterpret_cast<LPBYTE>(buf), &outl, ptr, len);
#if defined(_DEBUG) || defined(DEBUG)
if (ret <= 0)
{
unsigned long err = ERR_get_error();
char err_msg[1024] = { 0 };
ERR_error_string(err, err_msg);
printf("err msg: err:%ld, msg:%s\n", err, err_msg);
}
#endif
if (ret > 0)
{
de_data.append(buf, outl);
}
ptr += len;
}
delete[] buf;
break;
}
if (pKey)
EVP_PKEY_free(pKey);
if (ctx)
EVP_PKEY_CTX_free(ctx);
return de_data;
}
}
下面是测试代码, 自行引用上面的代码
openssl怎么安装可以用vcpkg安装
vcpkg install openssl:x86-windows-static
经过我的测试, vs安装路径中带有空格的话
vcpkg安装会失败, 花了一天重装vs发现的
int main()
{
std::string pri_key, pub_key;
openssl_rsa_3_x::GenerateKeys1(pri_key, pub_key);
std::string en_data = openssl_rsa_3_x::rsa_encrypt(pri_key.c_str(), pri_key.size(), pub_key.c_str());
std::string de_data = openssl_rsa_3_x::rsa_decrypt(en_data.c_str(), en_data.size(), pri_key.c_str());
bool b = de_data == pri_key;
std::cout << "解密后的值和加密前的值对比结果: " << b << std::endl;
return 0;
}