前言
我使用的是OpenSSL 1.1.1版本,在对项目的设置中在我前面的文章从0到1简单开始使用OpenSSL有提到,除此之外因为这个代码有部分地方会触发堆栈异常,但是我并没有找到是在哪里,所以还需要在代码生成选项中->基本运行时检测改为默认值
生成PEM格式公钥/私钥命令
生成私钥
openssl genpkey -algorithm RSA -out private.pem
生成公钥
openssl pkey -in private.pem -pubout -out public.pem
验证是否生成成功,如果下面两条cmd命令的结果是一致说明成功
openssl pkey -in private.pem -pubout -outform pem
openssl pkey -in public.pem -pubin -outform pem
代码演示
然后把下面代码的公钥私钥路径换成自己的,这样便可以直接使用了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
int encrypt_with_public_key(const unsigned char* plaintext, int plaintext_len,
const char* public_key_file, unsigned char* ciphertext, int* ciphertext_len)
{
//这里注意要用BIO流进行读取,否则后面会直接失败
BIO* bio = BIO_new_file(public_key_file, "rb");
if (bio == NULL) {
fprintf(stderr, "Failed to open file '%s'.\n", public_key_file);
return 0;
}
EVP_PKEY* pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
BIO_free_all(bio);
if (pkey == NULL)
{
fprintf(stderr, "Failed to read public key.\n");
return 0;
}
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey, NULL);
if (ctx == NULL)
{
fprintf(stderr, "Failed to create EVP context.\n");
EVP_PKEY_free(pkey);
return 0;
}
if (EVP_PKEY_encrypt_init(ctx) <= 0)
{
fprintf(stderr, "Failed to initialize encryption context.\n");
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return 0;
}
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
{
fprintf(stderr, "Failed to set encryption padding.\n");
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return 0;
}
if (EVP_PKEY_encrypt(ctx, ciphertext, ciphertext_len, plaintext, plaintext_len) <= 0)
{
fprintf(stderr, "Failed to encrypt data.\n");
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return 0;
}
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
return 1;
}
int decrypt_with_private_key(const unsigned char* ciphertext, int ciphertext_len,
const char* private_key_file, unsigned char* plaintext, int* plaintext_len)
{
//这里注意要用BIO流进行读取,否则后面会直接失败
BIO* bio = BIO_new_file(private_key_file, "rb");
if (bio == NULL) {
fprintf(stderr, "Failed to open file '%s'.\n", private_key_file);
return 0;
}
EVP_PKEY* pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
BIO_free_all(bio);
if (pkey == NULL)
{
fprintf(stderr, "Failed to read private key.\n");
return 0;
}
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey, NULL);
if (ctx == NULL)
{
fprintf(stderr, "Failed to create EVP context.\n");
EVP_PKEY_free(pkey);
return 0;
}
if (EVP_PKEY_decrypt_init(ctx) <= 0)
{
fprintf(stderr, "Failed to initialize decryption context.\n");
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return 0;
}
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
{
fprintf(stderr, "Failed to set decryption padding.\n");
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return 0;
}
if (EVP_PKEY_decrypt(ctx, plaintext, plaintext_len, ciphertext, ciphertext_len) <= 0)
{
fprintf(stderr, "Failed to decrypt data.\n");
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return 0;
}
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
return 1;
}
int main()
{
const char* public_key_file = "public.pem";
const char* private_key_file = "private.pem";
const unsigned char plaintext[] = "Hello World!";
unsigned char ciphertext[4096];
unsigned char decryptedtext[4096];
int decryptedtext_len = 0;
int ciphertext_len = 0;
if (!encrypt_with_public_key(plaintext, strlen(plaintext),
public_key_file, ciphertext, &ciphertext_len))
{
return 1;
}
printf("Ciphertext: ");
for (int i = 0; i < ciphertext_len; i++)
{
printf("%02x", ciphertext[i]);
}
printf("\n");
if (!decrypt_with_private_key(ciphertext, ciphertext_len,
private_key_file, decryptedtext, &decryptedtext_len))
{
return 1;
}
decryptedtext[decryptedtext_len] = '\0';
printf("Decrypted text: %s\n", decryptedtext);
return 0;
}