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