OpenSSL之RSA学习

前言

我使用的是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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值