rsa加密的public key格式有多種,常見的有兩種,
一種密鑰頭為‘-----BEGIN RSA PUBLIC KEY-----’,
一種開頭為‘-----BEGIN PUBLIC KEY-----’,
二者分别對應rsa的PKCS#1和PKCS#8格式。
使用openssl庫加載rsa的公鑰時,使用的函數也不同。以字元串公鑰為例,對PKCS#1格式的密鑰加載使用PEM_read_bio_RSAPublicKey()函數,對PKCS#8格式公鑰的加載使用PEM_read_bio_RSA_PUBKEY()函數。
對于不那麼熟悉rsa的同學,使用時注意區分者,可以減少不必要的麻煩。
// ---- rsa非對稱加解密 ---- //
#define KEY_LENGTH 512 // 密鑰長度
#define PUB_KEY_FILE "pubkey.pem" // 公鑰路徑
#define PRI_KEY_FILE "prikey.pem" // 私鑰路徑
生成密鑰對方法:
// 函數方法生成密鑰對
void rsa::generateRSAKey(std::string strKey[2])
{
// 公私密鑰對
size_t pri_len;
size_t pub_len;
char *pri_key = NULL;
char *pub_key = NULL;
// 生成密鑰對
RSA *keypair = RSA_generate_key(KEY_LENGTH, RSA_3, 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);
}
1、已知公鑰密鑰 進行加密 和解密
加載公鑰
#include <openssl/pem.h>
#include <openssl/err.h>
RSA* rsa::CreatePubKey()
{
RSA*pPubKey_ = NULL;
BIO* bp = NULL;
std::string strPublicKey = "-----BEGIN RSA PUBLIC KEY-----\n\
MEYCQQDtWr6MU1o9GQdepJMdrRJsDyA9/ENMNxKd5+Vja794dJGQF4rPEY/1jjUZ\n\
NrDpY8z3r+2zc9BoKlc1oVs+0Ri7AgED\n\
-----END RSA PUBLIC KEY-----\n";
char *chPublicKey = const_cast<char *>(strPublicKey.c_str());
if ((bp = BIO_new_mem_buf(chPublicKey, -1)) == NULL)
{
printf("BIO_new_mem_buf failed!\n");
return pPubKey_;
}
//PEM_read_bio_RSAPublicKey
pPubKey_ = PEM_read_bio_RSAPublicKey(bp, NULL, NULL, NULL);
if (NULL == pPubKey_)
{
ERR_load_crypto_strings();
char errBuf[512];
ERR_error_string_n(ERR_get_error(), errBuf, sizeof(errBuf));
printf("load public key failed[%s]\n", errBuf);
return pPubKey_;
}
BIO_free_all(bp);
return pPubKey_;
}
加載密鑰
RSA* rsa::CreatePriKey()
{
RSA*pPubKey_ = NULL;
BIO* bp = NULL;
std::string strPublicKey = "-----BEGIN RSA PRIVATE KEY-----\n\
MIIBOgIBAAJBAO1avoxTWj0ZB16kkx2tEmwPID38Q0w3Ep3n5WNrv3h0kZAXis8R\n\
j/WONRk2sOljzPev7bNz0GgqVzWhWz7RGLsCAQMCQQCePH8IN5F+EK+UbbdpHgxI\n\
ChV+qCzdegxpRUOXnSpQTG2vcBaQlHDWHUurJCBECokOsDWZhXtMOI5ruPhMHEoL\n\
AiEA+V181QCm02k1S2UhLQfZ6spLi7NUP+J5vvx4GBJ7VKMCIQDzq3KT9YwTSyz4\n\
M19Te3oUl1wRmddXk1vCl5POuitVCQIhAKY+UzirGeJGI4eYwMiv5pyG3QfM4tVB\n\
pn9S+rq2/OMXAiEAonJMYqOyt4dzUCI/jPz8Dbo9YRE6OmI9LGUNNHwc41sCIA3l\n\
XdHvymRjRzXXSlf1IvW7QSEwhYO0ifGXsrTd3t5d\n\
-----END RSA PRIVATE KEY-----\n";
char *chPublicKey = const_cast<char *>(strPublicKey.c_str());
if ((bp = BIO_new_mem_buf(chPublicKey, -1)) == NULL)
{
printf("BIO_new_mem_buf failed!\n");
return pPubKey_;
}
pPubKey_ = PEM_read_bio_RSAPrivateKey(bp, NULL, NULL, NULL);
if (NULL == pPubKey_)
{
ERR_load_crypto_strings();
char errBuf[512];
ERR_error_string_n(ERR_get_error(), errBuf, sizeof(errBuf));
printf("load public key failed[%s]\n", errBuf);
return pPubKey_;
}
BIO_free_all(bp);
return pPubKey_;
}
公鑰加密:
// 公鑰加密
std::string rsa::rsa_pub_encrypt(const std::string &clearText)
{
std::string strRet;
RSA* rsa = CreatePubKey();
int len = RSA_size(rsa);
//int len = 1028;
char *encryptedText = (char *)malloc(len + 1);
memset(encryptedText, 0, len + 1);
// 加密函數
int ret = RSA_public_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::rsa_pri_decrypt(const std::string &cipherText)
{
std::string strRet;
RSA* rsa = CreatePriKey();
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;
}
2、從檔案pubkey.pem 和prikey.pem 讀取公鑰和密鑰
公鑰加密:
// 公鑰加密
std::string rsa::rsa_pub_encrypt(const std::string &clearText, std::string &pubKey)
{
std::string strRet;
BIO * key = NULL;
RSA * rsa = NULL;
key = BIO_new(BIO_s_file());
BIO_read_filename(key, PUB_KEY_FILE);
rsa = PEM_read_bio_RSAPublicKey(key, NULL, NULL, NULL);
int len = RSA_size(rsa);
char *decryptedText = (char *)malloc(len + 1);
memset(decryptedText, 0, len + 1);
int lenf = clearText.length();
// 加密函數
int ret = RSA_public_encrypt(lenf, (const unsigned char*)clearText.c_str(), (unsigned char*)decryptedText, rsa, RSA_PKCS1_OAEP_PADDING);
if (ret >= 0)
strRet = std::string(decryptedText, ret);
// 釋放記憶體
free(decryptedText);
BIO_free_all(key);
RSA_free(rsa);
return strRet;
//方式二
/*std::string strRet;
RSA *rsa;
BIO * key = NULL;
FILE *fp;
if ((fp = fopen(PUB_KEY_FILE, "r")) == NULL) {
return "";
}
rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL);
int len = RSA_size(rsa);
char *encryptedText = (char *)malloc(len + 1);
memset(encryptedText, 0, len + 1);
// 加密函數
int ret = RSA_public_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(key);
RSA_free(rsa);
return strRet;*/
}
私鑰解密:
// 私鑰解密
std::string rsa::rsa_pri_decrypt(const std::string &cipherText, const std::string &priKey)
{
//方式一
std::string strRet;
BIO * key = NULL;
RSA * rsa = NULL;
key = BIO_new(BIO_s_file());
BIO_read_filename(key, PRI_KEY_FILE);
rsa = PEM_read_bio_RSAPrivateKey(key, NULL, NULL, NULL);
int len = RSA_size(rsa);
char *decryptedText = (char *)malloc(len + 1);
memset(decryptedText, 0, len + 1);
// 解密函數
int lenf = cipherText.length();
int ret = RSA_private_decrypt(lenf, (const unsigned char*)cipherText.c_str(), (unsigned char*)decryptedText, rsa, RSA_PKCS1_OAEP_PADDING);
if (ret >= 0)
strRet = std::string(decryptedText, ret);
/
// 釋放記憶體
free(decryptedText);
BIO_free_all(key);
RSA_free(rsa);
return strRet;
/* std::string strRet;
BIO * key = NULL;
RSA * rsa = NULL;
key = BIO_new(BIO_s_file());
BIO_read_filename(key, PUB_KEY_FILE);
rsa = PEM_read_bio_RSAPublicKey(key, NULL, 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(key);
RSA_free(rsa);
return strRet;*/
}