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

求基于BIO_f_cipher()与BIO_set_cipher()的C语言对称加解密示例

使用BIO_f_cipher()实现对称加解密的C语言示例

以下是基于OpenSSL的BIO_f_cipher()和BIO_set_cipher()实现对称加解密的完整示例,包含加密、解密两个流程:

加密示例代码

#include <stdio.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/err.h>

#define BUFFER_SIZE 1024

void handle_errors() {
    ERR_print_errors_fp(stderr);
    abort();
}

int encrypt_data(const unsigned char *plaintext, int plaintext_len,
                 const unsigned char *key, const unsigned char *iv,
                 unsigned char *ciphertext) {
    BIO *bio_cipher = NULL, *bio_mem = NULL;
    int ciphertext_len = 0;
    int bytes_written;

    // 初始化OpenSSL算法与错误处理
    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();

    // 创建内存BIO存储加密结果
    bio_mem = BIO_new(BIO_s_mem());
    if (!bio_mem) handle_errors();

    // 创建密码处理BIO
    bio_cipher = BIO_new(BIO_f_cipher());
    if (!bio_cipher) handle_errors();

    // 设置加密算法、密钥、IV,最后参数1表示加密模式
    if (!BIO_set_cipher(bio_cipher, EVP_aes_256_cbc(), key, iv, 1)) {
        handle_errors();
    }

    // 拼接BIO链:密码BIO在前,内存BIO在后
    bio_cipher = BIO_push(bio_cipher, bio_mem);

    // 写入明文进行加密
    bytes_written = BIO_write(bio_cipher, plaintext, plaintext_len);
    if (bytes_written <= 0) handle_errors();

    // 刷新BIO确保所有数据完成加密
    if (BIO_flush(bio_cipher) <= 0) handle_errors();

    // 从内存BIO读取加密后的数据
    ciphertext_len = BIO_read(bio_mem, ciphertext, BUFFER_SIZE);

    // 释放资源
    BIO_free_all(bio_cipher);
    EVP_cleanup();
    ERR_free_strings();

    return ciphertext_len;
}

int main() {
    // AES-256需要32字节密钥、16字节IV,实际使用建议用随机生成值
    unsigned char key[32] = "0123456789abcdef0123456789abcdef";
    unsigned char iv[16] = "0123456789abcdef";
    unsigned char plaintext[] = "这是需要加密的测试数据";
    unsigned char ciphertext[BUFFER_SIZE] = {0};

    int ciphertext_len = encrypt_data(plaintext, strlen((char *)plaintext), key, iv, ciphertext);

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

    return 0;
}

解密示例代码

#include <stdio.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/err.h>

#define BUFFER_SIZE 1024

void handle_errors() {
    ERR_print_errors_fp(stderr);
    abort();
}

int decrypt_data(const unsigned char *ciphertext, int ciphertext_len,
                 const unsigned char *key, const unsigned char *iv,
                 unsigned char *plaintext) {
    BIO *bio_cipher = NULL, *bio_mem = NULL;
    int plaintext_len = 0;

    // 初始化OpenSSL算法与错误处理
    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();

    // 创建内存BIO并加载密文数据
    bio_mem = BIO_new_mem_buf(ciphertext, ciphertext_len);
    if (!bio_mem) handle_errors();

    // 创建密码处理BIO
    bio_cipher = BIO_new(BIO_f_cipher());
    if (!bio_cipher) handle_errors();

    // 设置解密算法、密钥、IV,最后参数0表示解密模式
    if (!BIO_set_cipher(bio_cipher, EVP_aes_256_cbc(), key, iv, 0)) {
        handle_errors();
    }

    // 拼接BIO链:密码BIO在前,内存BIO在后
    bio_cipher = BIO_push(bio_cipher, bio_mem);

    // 读取解密后的明文数据
    plaintext_len = BIO_read(bio_cipher, plaintext, BUFFER_SIZE);
    if (plaintext_len <= 0) handle_errors();

    // 添加字符串结束符
    plaintext[plaintext_len] = '\0';

    // 释放资源
    BIO_free_all(bio_cipher);
    EVP_cleanup();
    ERR_free_strings();

    return plaintext_len;
}

int main() {
    // 使用与加密时完全相同的密钥和IV
    unsigned char key[32] = "0123456789abcdef0123456789abcdef";
    unsigned char iv[16] = "0123456789abcdef";
    // 替换为实际加密得到的密文字节数组
    unsigned char ciphertext[] = { /* 此处填入加密后的十六进制对应字节 */ };
    int ciphertext_len = sizeof(ciphertext);
    unsigned char plaintext[BUFFER_SIZE] = {0};

    int plaintext_len = decrypt_data(ciphertext, ciphertext_len, key, iv, plaintext);

    printf("解密后数据长度: %d\n", plaintext_len);
    printf("解密后数据: %s\n", plaintext);

    return 0;
}

关键注意事项

  • BIO链逻辑:通过BIO_push()将密码BIO与存储BIO(示例用内存BIO)拼接,数据会自动流经密码BIO完成加解密。
  • 算法适配:示例用AES-256-CBC,如需更换算法(如3DES),需对应调整密钥、IV长度,并替换EVP_aes_256_cbc()为对应算法函数。
  • 资源管理:必须调用BIO_free_all()释放整个BIO链,避免内存泄漏;同时要清理OpenSSL的全局资源。
  • 安全建议:实际生产环境中,密钥和IV应使用密码学安全的随机数生成,而非固定字符串。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 13:28:28