求基于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
相关产品推荐
相关产品推荐

