You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C语言中用OpenSSL库自动生成密钥对并实现加解密?

在C语言中使用OpenSSL自动生成密钥对并实现加解密的完整指南

Got it!既然你已经能用固定密钥完成OpenSSL加解密了,那自动生成密钥对(不管是非对称的RSA密钥对,还是对称加密的随机密钥)其实都是OpenSSL的标准操作。下面我分情况给你拆解具体步骤,再附上可运行的代码示例,帮你快速落地。

一、非对称加密(RSA密钥对):公钥加密,私钥解密

如果你的场景需要跨主体安全传输数据,RSA是最常用的非对称加密选择。以下是完整实现步骤:

1. 初始化OpenSSL环境

首先要初始化OpenSSL的加密库,不同版本的初始化方式略有差异,这里推荐适配1.1.0+版本的新接口:

OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);

如果是1.0.x版本,替换为:

SSL_library_init();
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();

2. 生成RSA密钥对

创建RSA结构体,指定密钥长度(推荐2048位及以上,兼顾安全和性能)和公钥指数(通常用RSA_F4即65537):

RSA *rsa = RSA_new();
BIGNUM *bne = BN_new();
BN_set_word(bne, RSA_F4);
// 生成2048位密钥对
RSA_generate_key_ex(rsa, 2048, bne, NULL);

3. 提取/导出密钥(可选)

可以把公钥和私钥导出为PEM格式(方便存储或传输),也可以直接在内存中使用:

// 导出公钥到内存BIO
BIO *pub_bio = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPublicKey(pub_bio, rsa);
// 导出私钥到内存BIO
BIO *pri_bio = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPrivateKey(pri_bio, rsa, NULL, NULL, 0, NULL, NULL);

4. 公钥加密数据

使用RSA_public_encrypt函数,注意明文长度不能超过密钥长度-11(PKCS#1 v1.5填充规则),2048位RSA最多加密245字节:

const char *plaintext = "Hello, OpenSSL RSA!";
unsigned char ciphertext[256]; // 2048位RSA加密后固定256字节
int cipher_len = RSA_public_encrypt(strlen(plaintext), 
                                   (unsigned char*)plaintext,
                                   ciphertext, rsa, RSA_PKCS1_PADDING);

5. 私钥解密数据

用RSA_private_decrypt对应解密,填充方式要和加密一致:

unsigned char decrypted[256];
int decrypted_len = RSA_private_decrypt(cipher_len, ciphertext,
                                       decrypted, rsa, RSA_PKCS1_PADDING);
decrypted[decrypted_len] = '\0'; // 添加字符串结束符

6. 清理资源

OpenSSL的结构体必须手动释放,避免内存泄漏:

RSA_free(rsa);
BN_free(bne);
BIO_free(pub_bio);
BIO_free(pri_bio);
EVP_cleanup();
ERR_free_strings();

二、完整可运行的RSA示例代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>

// 错误处理函数,打印OpenSSL错误信息
void handle_errors() {
    ERR_print_errors_fp(stderr);
    abort();
}

int main() {
    // 初始化OpenSSL环境(适配1.1.0+)
    OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
    OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);

    RSA *rsa = NULL;
    BIGNUM *bne = NULL;
    const int bits = 2048;
    const unsigned long e = RSA_F4;

    // 创建并生成RSA密钥对
    bne = BN_new();
    if (!BN_set_word(bne, e)) handle_errors();

    rsa = RSA_new();
    if (!RSA_generate_key_ex(rsa, bits, bne, NULL)) handle_errors();

    // 导出公钥和私钥到内存
    BIO *pub_bio = BIO_new(BIO_s_mem());
    BIO *pri_bio = BIO_new(BIO_s_mem());
    if (!PEM_write_bio_RSAPublicKey(pub_bio, rsa)) handle_errors();
    if (!PEM_write_bio_RSAPrivateKey(pri_bio, rsa, NULL, NULL, 0, NULL, NULL)) handle_errors();

    // 打印密钥(可选,用于验证)
    char pub_key[2048], pri_key[4096];
    int pub_len = BIO_read(pub_bio, pub_key, sizeof(pub_key)-1);
    int pri_len = BIO_read(pri_bio, pri_key, sizeof(pri_key)-1);
    pub_key[pub_len] = '\0';
    pri_key[pri_len] = '\0';
    printf("=== 生成的公钥 ===\n%s\n", pub_key);
    printf("=== 生成的私钥 ===\n%s\n", pri_key);

    // 准备明文并加密
    const char *plaintext = "这是一段要加密的测试字符串!";
    unsigned char ciphertext[256];
    int cipher_len = RSA_public_encrypt(strlen(plaintext), 
                                       (unsigned char*)plaintext,
                                       ciphertext, rsa, RSA_PKCS1_PADDING);
    if (cipher_len == -1) handle_errors();

    printf("\n=== 加密后数据(十六进制) ===\n");
    for (int i=0; i<cipher_len; i++) {
        printf("%02x", ciphertext[i]);
    }
    printf("\n");

    // 解密数据
    unsigned char decrypted[256];
    int decrypted_len = RSA_private_decrypt(cipher_len, ciphertext,
                                           decrypted, rsa, RSA_PKCS1_PADDING);
    if (decrypted_len == -1) handle_errors();
    decrypted[decrypted_len] = '\0';
    printf("\n=== 解密后明文 ===\n%s\n", decrypted);

    // 清理所有资源
    RSA_free(rsa);
    BN_free(bne);
    BIO_free(pub_bio);
    BIO_free(pri_bio);
    EVP_cleanup();
    ERR_free_strings();

    return 0;
}

编译命令:

gcc -o rsa_demo rsa_demo.c -lcrypto

三、对称加密(AES):生成随机密钥+IV

如果你的场景是单主体加解密(比如本地存储),对称加密更高效。此时不需要密钥对,而是生成随机的密钥和初始化向量(IV):

核心步骤

  1. 用RAND_bytes生成随机密钥(AES-128用16字节,AES-256用32字节)和IV(通常16字节)
  2. 使用OpenSSL的EVP高级接口完成加解密(比低级接口更安全)

示例代码片段

#include <openssl/evp.h>
#include <openssl/rand.h>

// 生成AES-256密钥和IV
unsigned char aes_key[32], aes_iv[16];
if (!RAND_bytes(aes_key, sizeof(aes_key)) || !RAND_bytes(aes_iv, sizeof(aes_iv))) {
    handle_errors();
}

// 后续使用EVP_CIPHER_CTX_new()、EVP_EncryptInit_ex()等接口完成加解密

四、关键注意事项

  • 密钥长度:RSA推荐至少2048位,1024位已被破解;AES推荐用256位。
  • 填充方式:RSA推荐用RSA_OAEP_PADDING(比PKCS#1更安全),对称加密默认用PKCS#7填充。
  • 大文件加密:RSA只能加密小数据,大文件建议用混合加密:RSA加密AES密钥,AES加密文件。
  • 随机数安全:生成密钥/IV时必须用RAND_bytes(加密安全的随机数生成器),不能用普通的rand()。

内容的提问来源于stack exchange,提问作者a verma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:46:13