最近学习了Openssl中rsa的加密过程,并生成了保存在本地的密钥对,用的是openssl3.1.1版本,在此记录。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <error.h>
void generateKeyFiles()
{
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
if (ctx == NULL) {
printf("Error creating EVP_PKEY_CTX.\n");
return;
}
if (EVP_PKEY_keygen_init(ctx) <= 0) {
printf("Error initializing key generation.\n");
EVP_PKEY_CTX_free(ctx);
return;
}
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 1024) <= 0) {
printf("Error setting key size.\n");
EVP_PKEY_CTX_free(ctx);
return;
}
EVP_PKEY *pkey = NULL;
if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
printf("Error generating RSA key.\n");
EVP_PKEY_CTX_free(ctx);
return;
}
EVP_PKEY_CTX_free(ctx);
// 保存公钥到文件
FILE *pub_file = fopen("public.pem", "w");
if (pub_file != NULL) {
BIO *pub_bio = BIO_new_file("public.pem", "w");
if (pub_bio != NULL) {
if (PEM_write_bio_PUBKEY(pub_bio, pkey) == 1) {
BIO_free(pub_bio);
fclose(pub_file);
} else {
printf("Error writing public key to file.\n");
BIO_free(pub_bio);
fclose(pub_file);
remove("public.pem");
}
} else {
printf("Error creating BIO object for public key.\n");
fclose(pub_file);
remove("public.pem");
}
} else {
perror("File error");
}
// 保存私钥到文件
FILE *priv_file = fopen("private.pem", "w");
if (priv_file != NULL) {
BIO *priv_bio = BIO_new_file("private.pem", "w");
if (priv_bio != NULL) {
if (PEM_write_bio_PrivateKey(priv_bio, pkey, NULL, NULL, 0, NULL, NULL) == 1) {
BIO_free(priv_bio);
fclose(priv_file);
} else {
printf("Error writing private key to file.\n");
BIO_free(priv_bio);
fclose(priv_file);
remove("private.pem");
}
} else {
printf("Error creating BIO object for private key.\n");
fclose(priv_file);
remove("private.pem");
}
} else {
perror("File error");
}
EVP_PKEY_free(pkey);
}
int main()
{
generateKeyFiles();
BIO *pub_bio = BIO_new_file("public.pem", "r");
if (pub_bio == NULL) {
perror("Failed to open public key file.");
return 1;
}
EVP_PKEY *pub_key = PEM_read_bio_PUBKEY(pub_bio, NULL, NULL, NULL);
BIO_free(pub_bio);
if (pub_key == NULL) {
printf("Failed to read public key from file.\n");
return 1;
}
BIO *priv_bio = BIO_new_file("private.pem", "r");
if (priv_bio == NULL) {
perror("Failed to open private key file.");
EVP_PKEY_free(pub_key);
return 1;
}
EVP_PKEY *priv_key = PEM_read_bio_PrivateKey(priv_bio, NULL, NULL, NULL);
BIO_free(priv_bio);
if (priv_key == NULL) {
printf("Failed to read private key from file.\n");
EVP_PKEY_free(pub_key);
return 1;
}
// 待加密的数据
unsigned char plaintext[] = "Hello, RSA!";
size_t plaintext_len = sizeof(plaintext) - 1;
// 加密后的数据缓冲区
unsigned char ciphertext[256];
size_t ciphertext_len = 0;
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pub_key, NULL);
if (ctx == NULL) {
printf("Error creating EVP_PKEY_CTX for encryption.\n");
EVP_PKEY_free(pub_key);
EVP_PKEY_free(priv_key);
return 1;
}
if (EVP_PKEY_encrypt_init(ctx) <= 0) {
printf("Error initializing RSA encryption.\n");
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pub_key);
EVP_PKEY_free(priv_key);
return 1;
}
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) {
printf("Error setting RSA padding.\n");
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pub_key);
EVP_PKEY_free(priv_key);
return 1;
}
if (EVP_PKEY_encrypt(ctx, ciphertext, &ciphertext_len, plaintext, plaintext_len) <= 0) {
printf("RSA encryption failed.\n");
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pub_key);
EVP_PKEY_free(priv_key);
return 1;
}
printf("Ciphertext: ");
for (size_t i = 0; i < ciphertext_len; i++) {
printf("%02x", ciphertext[i]);
}
printf("\n");
EVP_PKEY_CTX_free(ctx);
// 解密后的数据缓冲区
unsigned char *decrypted_text;
size_t decrypted_text_len = 0;
EVP_PKEY_CTX *ctx1 = EVP_PKEY_CTX_new(priv_key, NULL);
if (ctx1 == NULL) {
printf("Error creating EVP_PKEY_CTX for decryption.\n");
EVP_PKEY_free(pub_key);
EVP_PKEY_free(priv_key);
return 1;
}
if (EVP_PKEY_decrypt_init(ctx1) <= 0) {
printf("Error initializing RSA decryption.\n");
EVP_PKEY_CTX_free(ctx1);
EVP_PKEY_free(pub_key);
EVP_PKEY_free(priv_key);
return 1;
}
//此处先进行解密明文的长度的初始化
EVP_PKEY_decrypt(ctx1, NULL, &decrypted_text_len, ciphertext, ciphertext_len);
//按照长度开辟空间
decrypted_text = malloc(plaintext_len + 1);
//填充
if (EVP_PKEY_CTX_set_rsa_padding(ctx1, RSA_PKCS1_PADDING) <= 0) {
printf("Error setting RSA padding.\n");
EVP_PKEY_CTX_free(ctx1);
EVP_PKEY_free(pub_key);
EVP_PKEY_free(priv_key);
return 1;
}
//再进行解密
if (EVP_PKEY_decrypt(ctx1, decrypted_text, &decrypted_text_len, ciphertext, ciphertext_len) <= 0) {
printf("RSA decryption failed.\n");
system("pause");
EVP_PKEY_CTX_free(ctx1);
EVP_PKEY_free(pub_key);
EVP_PKEY_free(priv_key);
return 1;
}
decrypted_text[decrypted_text_len] = '\0';
printf("Decrypted Text: %s\n", decrypted_text);
EVP_PKEY_CTX_free(ctx1);
EVP_PKEY_free(pub_key);
EVP_PKEY_free(priv_key);
//system("pause");
return 0;
}
windows和linux都适用,注意包含头文件和静态库