【C语言】使用 OpenSSL 进行 AES CBC 加密与解密
使用 OpenSSL 进行 AES CBC 加密与解密
在这篇文章中,我们将使用 OpenSSL 库实现 AES CBC 模式的加密和解密功能。AES(高级加密标准)是一种对称加密算法,广泛应用于数据保护。本示例展示了如何使用 PKCS#7 填充标准来处理明文的长度,以及如何确保在加密和解密过程中正确管理密钥和初始化向量(IV)。
代码实现
下面是实现 AES CBC 加密与解密的完整代码:
#include <stdio.h>
#include <string.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
// PKCS#7 去除填充的函数
int pkcs7_unpad(unsigned char *data, int len) {
int padding = data[len - 1];
if (padding < 1 || padding > AES_BLOCK_SIZE) {
return -2; // 错误的填充
}
for (int i = len - padding; i < len; i++) {
if (data[i] != padding) return -1; // 填充不正确
}
return len - padding;
}
// PKCS#7 填充函数
void pkcs7_pad(unsigned char *plaintext, int plaintext_len, int block_size) {
int padding = block_size - (plaintext_len % block_size);
memset(plaintext + plaintext_len, padding, padding);
}
// AES CBC 解密函数
int aes_cbc_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext) {
AES_KEY dec_key;
if (AES_set_decrypt_key(key, 256, &dec_key) < 0) {
return -2; // 设置解密密钥失败
}
int block_size = AES_BLOCK_SIZE;
if (ciphertext_len % block_size != 0) {
return -3; // 密文长度不是块大小的倍数
}
// 进行解密
AES_cbc_encrypt(ciphertext, plaintext, ciphertext_len, &dec_key, iv, AES_DECRYPT);
int plaintext_len = pkcs7_unpad(plaintext, ciphertext_len);
if (plaintext_len < 0) {
return plaintext_len; // 填充去除失败
}
return plaintext_len;
}
// AES CBC 加密函数
int aes_cbc_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext) {
AES_KEY enc_key;
AES_set_encrypt_key(key, 256, &enc_key);
int block_size = AES_BLOCK_SIZE;
int padding = block_size - (plaintext_len % block_size);
int ciphertext_len = plaintext_len + padding;
unsigned char plaintext2[ciphertext_len];
memcpy(plaintext2, plaintext, plaintext_len);
pkcs7_pad(plaintext2, plaintext_len, block_size);
AES_cbc_encrypt(plaintext2, ciphertext, ciphertext_len, &enc_key, iv, AES_ENCRYPT);
return ciphertext_len;
}
int main() {
// 假设的密钥和IV
unsigned char key[AES_BLOCK_SIZE * 2] = "your-256-bit-key-here-xxxxxxxxxx";
unsigned char iv[AES_BLOCK_SIZE] = "your-iv-here-xxx";
// 明文
unsigned char plaintext[] = "Hello,World";
int plaintext_len = strlen((char *)plaintext);
unsigned char *ciphertext_buffer = malloc(plaintext_len + AES_BLOCK_SIZE);
if (ciphertext_buffer == NULL) {
return 1;
}
int ret_len = aes_cbc_encrypt(plaintext, plaintext_len, key, iv, ciphertext_buffer);
unsigned char iv2[AES_BLOCK_SIZE] = "your-iv-here-xxx";
unsigned char *plaintext_buffer2 = malloc(plaintext_len + AES_BLOCK_SIZE);
int code = aes_cbc_decrypt(ciphertext_buffer, ret_len, key, iv2, plaintext_buffer2);
printf("Decrypted: %.*s\n", code, plaintext_buffer2);
free(ciphertext_buffer);
free(plaintext_buffer2);
return 0;
}
代码分析
1. 填充与去填充
我们使用 PKCS#7 填充标准来处理明文长度。这种填充方式确保了明文的长度是块大小的倍数,便于后续的加密操作。
2. AES 加密与解密
aes_cbc_encrypt
函数负责加密明文,而 aes_cbc_decrypt
函数则负责解密密文。在这两个函数中,我们都使用了相同的密钥和初始化向量。
3. 主函数
在 main
函数中,我们定义了明文、密钥和 IV。我们调用加密和解密函数,并打印出解密后的结果。
总结
本文展示了如何使用 OpenSSL 实现 AES CBC 模式的加密与解密。通过合理的填充和去填充机制,我们确保了数据的完整性与安全性。在实际应用中,请确保密钥和 IV 的安全性,以防止潜在的安全风险。
补充
环境:安装OpenSSL
1. Ubuntu/Debian
打开终端,运行以下命令:
sudo apt update
sudo apt install openssl libssl-dev
2. CentOS
对于 CentOS ,可以使用以下命令:
sudo yum install openssl openssl-devel
编译
gcc -o main main.c -lcrypto