天天看點

openssl庫實作rsa加解密1、已知公鑰密鑰 進行加密 和解密

 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;*/
}