AES加密模式详解及OpenSSL C库函数指南
AES加密模式概述
AES(高级加密标准)是一种对称分组加密算法,支持多种工作模式以适应不同的安全需求和应用场景。以下是五种主要加密模式的详细说明:
1. ECB模式(电子本密码模式)
工作原理 :将明文分成固定大小的块(128 位),每个块独立使用相同的密钥加密。
特点 :
- 不需要初始化向量(IV)
- 相同明文块总是产生相同密文块
- 容易受到重复攻击,安全性较低
适用场景 :加密独立的数据块或短报文。
2. CBC模式(密码分组链接模式)
工作原理 :每个明文块加密前先与前一个密文块异或,第一个块与 IV 异或。
特点 :
- 需要 IV
- 相同的明文块在不同位置会产生不同的密文
- 安全性高于 ECB
适用场景 :加密长度超过一个块的数据。
3. CFB模式(密文反馈模式)
工作原理 :将块密码转换为流密码,使用加密器加密 IV 数据,然后将明文最高位与 IV 最高位异或得到密文。
特点 :
- 支持不同反馈位数(CFB1, CFB8, CFB128 等)
- 适合对流数据进行加密
- 解密可以并行计算
适用场景 :需要流加密的场景。
4. OFB模式(输出反馈模式)
工作原理 :先用块加密器生成密钥流,再将密钥流与明文流异或得到密文流。
特点 :
- 加密和解密流程完全相同
- 错误不会传播
- 逜要确保 IV 的唯一性
适用场景 :需要流加密且对错误传播敏感的场景。
5. CTR模式(计数器模式)
工作原理 :使用计数器生成密钥流,然后将密钥流与明文异或。
特点 :
- 无填充需求
- 支持并行处理
- IV 必须是唯一且不可预测的
适用场景 :需要高效处理任意长度数据的场景。
OpenSSL中的AES加密函数
OpenSSL 提供了 EVP(Enveloped Public Key)高级加密接口来支持 AES 的各种加密模式。以下是各模式对应的函数及使用方法:
通用加密流程
// 初始化上下文
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ctx);
// 加密初始化
EVP_EncryptInit_ex(ctx, cipher_type, NULL, key, iv);
// 加密更新(可多次调用)
EVP_EncryptUpdate(ctx, out, &outl, in, inl);
// 加密结束
EVP_EncryptFinal_ex(ctx, out + outl, &tmplen);
// 清理
EVP_CIPHER_CTX_free(ctx);
各模式对应的EVP_CIPHER
加密模式 | OpenSSL EVP_CIPHER名称 | 说明 |
---|---|---|
ECB | EVP_aes_128_ecb, EVP_aes_192_ecb, EVP_aes_256_ecb | 电子密码本模式 |
CBC | EVP_aes_128_cbc, EVP_aes_192_cbc, EVP_aes_256_cbc | 密码分组链接模式 |
CFB | EVP_aes_128_cfb128, EVP_aes_192_cfb128, EVP_aes_256_cfb128 | 密码反馈模式(128 位反馈) |
OFB | EVP_aes_128_ofb, EVP_aes_192_ofb, EVP_aes_256_ofb | 输出反馈模式 |
CTR | EVP_aes_128_ctr, EVP_aes_192_ctr, EVP_aes_256_ctr | 计数器模式 |
各模式示例代码
1. CBC模式示例
int openssl_aes128_encrypt_cbc(unsigned char *key, unsigned char *iv,
unsigned char *in_buf, int in_len,
unsigned char *out_buf, int *out_len) {
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);
if(!EVP_EncryptUpdate(ctx, out_buf, out_len, in_buf, in_len)) {
EVP_CIPHER_CTX_free(ctx);
return -1;
}
int tmplen = 0;
if(!EVP_EncryptFinal_ex(ctx, out_buf + *out_len, &tmplen)) {
EVP_CIPHER_CTX_free(ctx);
return -1;
}
*out_len += tmplen;
EVP_CIPHER_CTX_free(ctx);
return 0;
}
2. CFB模式示例
int openssl_aes128_encrypt_cfb(unsigned char *key, unsigned char *iv,
unsigned char *in_buf, int in_len,
unsigned char *out_buf, int *out_len) {
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_aes_128_cfb(), NULL, key, iv);
EVP_CIPHER_CTX_set_padding(ctx, 0);
if(!EVP_EncryptUpdate(ctx, out_buf, out_len, in_buf, in_len)) {
EVP_CIPHER_CTX_free(ctx);
return -1;
}
int tmplen = 0;
if(!EVP_EncryptFinal_ex(ctx, out_buf + *out_len, &tmplen)) {
EVP_CIPHER_CTX_free(ctx);
return -1;
}
*out_len += tmplen;
EVP_CIPHER_CTX_free(ctx);
return 0;
}
3. OFB模式示例
int openssl_aes128_encrypt_ofb(unsigned char *key, unsigned char *iv,
unsigned char *in_buf, int in_len,
unsigned char *out_buf, int *out_len) {
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_aes_128_ofb(), NULL, key, iv);
EVP_CIPHER_CTX_set_padding(ctx, 0);
if(!EVP_EncryptUpdate(ctx, out_buf, out_len, in_buf, in_len)) {
EVP_CIPHER_CTX_free(ctx);
return -1;
}
int tmplen = 0;
if(!EVP_EncryptFinal_ex(ctx, out_buf + *out_len, &tmplen)) {
EVP_CIPHER_CTX_free(ctx);
return -1;
}
*out_len += tmplen;
EVP_CIPHER_CTX_free(ctx);
return 0;
}
4. CTR模式示例
int main() {
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
unsigned char key[AES_BLOCK_SIZE];
unsigned char iv[AES_BLOCK_SIZE];
RAND_bytes(key, sizeof(key));
RAND_bytes(iv, sizeof(iv));
unsigned char plaintext[] = "The quick brown fox jumps over the lazy dog";
unsigned char ciphertext[sizeof(plaintext)];
unsigned char decryptedtext[sizeof(plaintext)];
EVP_CIPHER_CTX *ctx;
int len;
// 初始化加密上下文
if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key, iv)) handleErrors();
// 执行加密操作
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, sizeof(plaintext))) handleErrors();
EVP_EncryptFinal_ex(ctx, ciphertext + len, &len);
// 解密过程类似
// ...
EVP_CIPHER_CTX_free(ctx);
return 0;
}
各模式对比与选择建议
特性 | ECB | CBC | CFB | OFB | CTR |
---|---|---|---|---|---|
需要 IV | 否 | 是 | 是 | 是 | 是 |
错误传播 | 无 | 有 | 有 | 无 | 无 |
并行加密 | 是 | 否 | 否 | 否 | 是 |
并行解密 | 是 | 是 | 是 | 否 | 是 |
填充需求 | 是 | 是 | 否 | 否 | 否 |
安全性 | 低 | 中 | 中 | 中 | 高 |
选择建议
- 避免使用 ECB 模式 :除非加密非常短且独立的数据块。
- 大多数应用选择 CBC 模式 :提供了良好的安全性和兼容性。
- 流加密场景 :考虑使用 CFB 或 OFB 模式。
- 高性能需求 :CTR 模式是较好的选择。
- IV 的重要性 :确保 IV 的唯一性和随机性,特别是对于 CBC、CFB、OFB 和 CTR 模式。
注意事项
- 密钥管理 :AES 是对称加密算法,密钥的安全性至关重要,应妥善保管。
- IV 生成 :对于需要 IV 的模式,应使用加密安全的随机数生成器生成 IV。
- 填充处理 :对于 ECB 和 CBC 模式,需要注意数据填充问题,可以使用 EVP_CIPHER_CTX_set_padding 控制填充行为。
- 错误处理 :OpenSSL 函数调用后应检查返回值,确保操作成功。
- 资源清理 :使用完 EVP_CIPHER_CTX 后应及时释放,避免内存泄漏。
通过合理选择加密模式并正确使用 OpenSSL 的 EVP 接口,可以实现安全高效的 AES 加密解密功能。