本文是在windows环境下,使用的是vs2019编译器。
下面是使用openssl静态库中的函数 实现的一个RSA加密字符串以及加密文件。
下面展示一些 本人实现代码
。
#pragma warning(disable:4996)
#include
#include
#include
#include
#include
#include
#include
// 私钥加密
#pragma comment(lib,"Iphlpapi.lib")
#pragma comment(lib,"libcrypto.lib")
#pragma comment(lib,"libssl.lib")
// ---- rsa非对称加解密 ---- //
#define KEY_LENGTH 1024 // 密钥长度
#define PUB_KEY_FILE "pubkey.pem" // 公钥路径
#define PRI_KEY_FILE "prikey.pem" // 私钥路径
// 函数方法生成密钥对
void generateRSAKey(std::string strKey[])
{
// 公私密钥对
size_t pri_len;
size_t pub_len;
char* pri_key = NULL;
char* pub_key = NULL;
// 生成密钥对
RSA* keypair = RSA_generate_key(KEY_LENGTH, RSA_F4, NULL, NULL);
BIO* pri = BIO_new(BIO_s_mem());
BIO* pub = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);
PEM_write_bio_RSAPublicKey(pub, keypair);
// 获取长度
pri_len = BIO_pending(pri);
pub_len = BIO_pending(pub);
// 密钥对读取到字符串
pri_key = (char*)malloc(pri_len + 1);
pub_key = (char*)malloc(pub_len + 1);
BIO_read(pri, pri_key, pri_len);
BIO_read(pub, pub_key, pub_len);
pri_key[pri_len] = '\0';
pub_key[pub_len] = '\0';
// 存储密钥对
strKey[0] = pub_key;
strKey[1] = pri_key;
// 存储到磁盘(这种方式存储的是begin rsa public key/ begin rsa private key开头的)
FILE* pubFile = fopen(PUB_KEY_FILE, "w");
if (pubFile == NULL)
{
assert(false);
return;
}
fputs(pub_key, pubFile);
fclose(pubFile);
FILE* priFile = fopen(PRI_KEY_FILE, "w");
if (priFile == NULL)
{
assert(false);
return;
}
fputs(pri_key, priFile);
fclose(priFile);
// 内存释放
RSA_free(keypair);
BIO_free_all(pub);
BIO_free_all(pri);
free(pri_key);
free(pub_key);
}
// 私钥加密
std::string rsa_pri_encrypt(const std::string& clearText, std::string& priKey)
{
std::string strRet;
BIO* keybio = BIO_new_mem_buf((const char*)priKey.c_str(), strlen(priKey.c_str()));
// 此处有三种方法
// 1, 读取内存里生成的密钥对,再从内存生成rsa
// 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa
// 3,直接从读取文件指针生成rsa
//RSA* pRSAPublicKey = RSA_new();
RSA* rsa = RSA_new();
rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL); // rsa = PEM_read_bio_RSAPublicKey(keybio, &rsa, NULL, NULL);如果要用公钥加密,函数要变化。
if (!rsa)
{
BIO_free_all(keybio);
return std::string("PEM_read_bio_RSAPrivateKey 错误");
}
int len = RSA_size(rsa);
//int len = 1028;
char* encryptedText = (char*)malloc(len + 1);
memset(encryptedText, 0, len + 1);
// 加密
int ret = RSA_private_encrypt(clearText.length(), (const unsigned char*)clearText.c_str(), (unsigned char*)encryptedText, rsa, RSA_PKCS1_PADDING);
if (ret >= 0)
strRet = std::string(encryptedText, ret);
// 释放内存
free(encryptedText);
BIO_free_all(keybio);
RSA_free(rsa);
return strRet;
}
// 公钥解密
std::string rsa_pub_decrypt(const std::string& clearText, std::string& pubKey)
{
std::string strRet;
BIO* keybio = BIO_new_mem_buf((unsigned char*)pubKey.c_str(), -1);
//keybio = BIO_new_mem_buf((unsigned char *)strPublicKey.c_str(), -1);
// 此处有三种方法
// 1, 读取内存里生成的密钥对,再从内存生成rsa
// 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa
// 3,直接从读取文件指针生成rsa
//RSA* pRSAPublicKey = RSA_new();
RSA* rsa = RSA_new();
rsa = PEM_read_bio_RSAPublicKey(keybio, &rsa, NULL, NULL); // rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);如果要私钥解密,函数要变化。
if (!rsa)
{
BIO_free_all(keybio);
return std::string("");
}
int len = RSA_size(rsa);
//int len = 1028;
char* encryptedText = (char*)malloc(len + 1);
memset(encryptedText, 0, len + 1);
//解密
int ret = RSA_public_decrypt(clearText.length(), (const unsigned char*)clearText.c_str(), (unsigned char*)encryptedText, rsa, RSA_PKCS1_PADDING);
if (ret >= 0)
strRet = std::string(encryptedText, ret);
// 释放内存
free(encryptedText);
BIO_free_all(keybio);
RSA_free(rsa);
return strRet;
}
//私钥加密 + 分片
std::string rsa_pri_split117_encrypt(const std::string& clearText, std::string& priKey)
{
std::string result;
std::string input;
result.clear();
for (int i = 0; i < clearText.length() / 117; i++)
{
input.clear();
input.assign(clearText.begin() + i * 117, clearText.begin() + i * 117 + 117);
result = result + rsa_pri_encrypt(input, priKey);
}
if (clearText.length() % 117 != 0)
{
int tem1 = clearText.length() / 117 * 117;
int tem2 = clearText.length() - tem1;
input.clear();
input.assign(clearText.begin() + tem1, clearText.end());
result = result + rsa_pri_encrypt(input, priKey);
}
return result;
}
//公钥解密 + 分片
std::string rsa_pub_split128_decrypt(const std::string& clearText, std::string& pubKey)
{
//Base64 *base = new Base64();
std::string result;
std::string input;
result.clear();
for (int i = 0; i < clearText.length() / 128; i++)
{
input.clear();
input.assign(clearText.begin() + i * 128, clearText.begin() + i * 128 + 128);
result = result + rsa_pub_decrypt(input, pubKey);
}
if (clearText.length() % 128 != 0)
{
int tem1 = clearText.length() / 128 * 128;
int tem2 = clearText.length() - tem1;
input.clear();
input.assign(clearText.begin() + tem1, clearText.end());
result = result + rsa_pri_encrypt(input, pubKey);
}
return result;
}
CHAR* OpenFile()
{
CHAR* pBuffer;
DWORD RSize;
int fileSize = 0;
HANDLE hOpenFile = (HANDLE)CreateFile(L"D:\\a.txt", GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if (hOpenFile == INVALID_HANDLE_VALUE)
{
hOpenFile = NULL;
MessageBoxA(NULL, "Can not open the file", "Playwav", MB_OK);
exit(1);
}
fileSize = GetFileSize(hOpenFile, NULL);
pBuffer = (CHAR*)malloc(fileSize);
ReadFile(hOpenFile, pBuffer, fileSize, &RSize, NULL);
//可将pBuffer显示在某区域或写入另一个文件来检查读出是否正确
FlushFileBuffers(hOpenFile);
CloseHandle(hOpenFile);
return pBuffer;
}
int main()
{
std::string strKey[] = {"1", "2"};
generateRSAKey(strKey);
std::string clearText = "aasdsadsadasd";
char* puffer = OpenFile();
std::string strRet = rsa_pri_split117_encrypt(puffer, strKey[1]);
std::cout << "加密后:" << strRet << std::endl;
std::string rRet = rsa_pub_split128_decrypt(strRet, strKey[0]);
std::cout << "解密后:" << rRet << std::endl;
system("pause");
return 0;
}
如果编译时发现出现链接错误,需要在属性中的附加库目录加上 ws2_32.lib、crypt32.lib这两个库。
本文部分代码来自以下链接,如果需要详细了解 可以点连接。https://www.cnblogs.com/azbane/p/10180464.html
感谢大家观看 同时如果发现问题 希望指出 大家一起进步