OpenSSL RSA加密和解密

rsa加密的密钥格式常见的有两种:
一种是PKCS#1,密钥头为

-----BEGIN RSA PUBLIC KEY-----

一种是PKCS#8,密钥头为

-----BEGIN PUBLIC KEY-----

以字符串公钥为例,对PKCS#1格式的密钥加载使用的函数是PEM_read_bio_RSAPublicKey(),而对PKCS#8格式公钥的加载使用的是函数PEM_read_bio_RSA_PUBKEY()。
 

1、生成密钥对

#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <stdio.h>
#include <iostream>
using namespace std;

#ifndef _WIN64
#pragma comment(lib, "libcrypto.lib")
#else
#pragma comment(lib, "libcrypto-x64.lib")
#endif // WIN32

#define KEY_LENGTH  1024             // 密钥长度  
#define PUB_KEY_FILE "pubkey.pem"    // 公钥路径  
#define PRI_KEY_FILE "prikey.pem"    // 私钥路径  

// 随机生成密钥字符串
BOOL generateRSAKey()
{
	// 公私密钥对    
	size_t pri_len;
	size_t pub_len;
	char *ucPriKey = NULL;
	char *ucPubKey = 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);

	// 密钥对读取到字符串
	ucPriKey = (char *)malloc(pri_len + 1);
	ucPubKey = (char *)malloc(pub_len + 1);

	BIO_read(pri, ucPriKey, pri_len);
	BIO_read(pub, ucPubKey, pub_len);

	ucPriKey[pri_len] = '\0';
	ucPubKey[pub_len] = '\0';

	// 存储密钥对    
	FILE *pubFile = fopen(PUB_KEY_FILE, "w");
	if (pubFile == NULL)
		return FALSE;

	fputs(ucPubKey, pubFile);
	fclose(pubFile);

	FILE *priFile = fopen(PRI_KEY_FILE, "w");
	if (priFile == NULL)
		return FALSE;

	fputs(ucPriKey , priFile);
	fclose(priFile);

	// 内存释放  
	RSA_free(keypair);
	BIO_free_all(pub);
	BIO_free_all(pri);

	free(ucPriKey);
	free(ucPubKey);
	return TRUE;
}

// 根据密钥字符串生成密钥对
RSA * createRSA(unsigned char * ucKey, bool IsPubkey)
{
	RSA *rsa = NULL;
	BIO *keybio;

	keybio = BIO_new_mem_buf(ucKey, -1);
	if (keybio == NULL)
	{
		printf("Failed to create key BIO");
		return 0;
	}

	if (IsPubkey)
	{
		rsa = PEM_read_bio_RSAPublicKey(keybio, &rsa, NULL, NULL);
	}
	else
	{
		rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);
	}
	
	if (rsa == NULL)
	{
		printf("Failed to create RSA");
	}

	return rsa;
}

2、公钥加密 -> 私钥解密

int public_encrypt(unsigned char * ucKey, int nKeyLen, unsigned char * ucPubKey, unsigned char *outData)
{
	RSA * rsa = createRSA(ucPubKey, 1);
	int  result = RSA_public_encrypt(nKeyLen, ucKey, outData, rsa, RSA_PKCS1_PADDING);
	if (rsa != NULL)
	{
		RSA_free(rsa);
		rsa = NULL;
	}

	return result;
}

int private_decrypt(unsigned char * ucKey, int nKeyLen, unsigned char * ucPriKey, unsigned char *outData)
{
	RSA * rsa = createRSA(ucPriKey, 0);
	int  result = RSA_private_decrypt(nKeyLen, ucKey, outData, rsa, RSA_PKCS1_PADDING);
	if (rsa != NULL)
	{
		RSA_free(rsa);
		rsa = NULL;
	}

	return result;
}

3、私钥加密 -> 公钥解密

int private_encrypt(unsigned char * ucKey, int nKeyLen, unsigned char * ucPriKey, unsigned char *outData)
{
	RSA * rsa = createRSA(ucPriKey, 0);
	int result = RSA_private_encrypt(nKeyLen, ucKey, outData, rsa, RSA_PKCS1_PADDING);
	if (rsa != NULL)
	{
		RSA_free(rsa);
		rsa = NULL;
	}

	return result;
}

int public_decrypt(unsigned char * ucKey, int ulKeyLen, unsigned char * ucPubKey, unsigned char *outData)
{
	RSA * rsa = createRSA(ucPubKey, 1);
	int  result = RSA_public_decrypt(ulKeyLen, ucKey, outData, rsa, RSA_PKCS1_PADDING);
	if (rsa != NULL)
	{
		RSA_free(rsa);
		rsa = NULL;
	}

	return result;
}

Guess you like

Origin blog.csdn.net/u012156872/article/details/118294274