AES_set_encrypt_key和AES_set_decrypt_key仅支持128、192、256位密钥长度,传入非标准值(如255或字节长度不匹配)返回-2;AES_cbc_encrypt要求明文长度为16字节整数倍,需手动PKCS#7填充;IV须每次加密前复制或重置,且不可复用;ECB模式不推荐用于生产环境。

AES_set_encrypt_key 和 AES_set_decrypt_key 的密钥长度必须严格匹配
OpenSSL 的 AES_set_encrypt_key 和 AES_set_decrypt_key 不接受任意长度的密钥,只认 128、192、256 这三个 bit 值。传入 16 字节密钥时必须填 128,32 字节必须填 256;哪怕只差 1 字节或参数写成 255,函数就直接返回 -2,且不报错信息,容易卡在“加密结果全零”这类静默失败上。
- 常见错误:用
std::string("mykey123")当密钥,长度是 8 字节 → 调用AES_set_encrypt_key(..., 128, ...)必败 - 正确做法:密钥必须提前补足(如用
PKCS#7填充逻辑)或哈希生成固定长度,例如EVP_Digest("mykey123", ..., MD5)得到 16 字节再传 - 注意:密钥缓冲区不能是临时栈变量(比如函数内定义的
unsigned char key[32]),若被后续操作覆盖,解密时会出错
AES_cbc_encrypt 要求明文长度是 AES_BLOCK_SIZE 的整数倍
AES_cbc_encrypt 是底层裸函数,不做任何填充处理。输入长度如果不是 16 字节(即 AES_BLOCK_SIZE)的倍数,它会静默截断或越界读取——典型表现是解密后末尾乱码、崩溃,或部分数据丢失。
- 必须手动填充:推荐 PKCS#7,即补
n字节,每个字节值为n;例如明文 10 字节,补 6 个0x06 - IV 必须独立传入且不可复用:
AES_cbc_encrypt会修改传入的ivec缓冲区,所以每次加密前要 memcpy 一份副本,或每次生成新 IV - 密文开头放 IV 是通用做法,但函数本身不负责拼接——你要自己
ciphertext.insert(ciphertext.begin(), iv.begin(), iv.end())
ECB 模式慎用,AES_ecb_encrypt 只处理单块 16 字节
AES_ecb_encrypt 每次只加密或解密一个 16 字节块,不能直接用于长字符串。有人误以为循环调用它就能实现 ECB 全文加密,但忘了它不自动分块、不检查边界,极易因长度不对导致越界访问。
- 明文 30 字节?得手动切成 16 + 14,第二块不足 16 就必须填充,否则
AES_ecb_encrypt会读取栈外内存 - ECB 安全性极低:相同明文块 → 相同密文块,图像加密后仍可辨轮廓,不适用于任何生产场景
- 如果真要用 ECB(比如兼容旧协议),务必确保所有块都严格 16 字节,并用
memset清零未用部分
别绕过 EVP 接口硬用 AES_* 函数,除非你控制全部上下文
直接调 AES_set_encrypt_key + AES_cbc_encrypt 看似轻量,但缺失 IV 随机生成、密钥派生(PBKDF2)、填充管理、错误码映射等关键能力。OpenSSL 官方早已建议优先用 EVP 系列接口,例如 EVP_EncryptInit_ex 自动处理 PKCS#7 填充、支持盐值、适配多种密钥格式。
立即学习“C++免费学习笔记(深入)”;
- 硬用底层函数时,
RAND_bytes(iv, AES_BLOCK_SIZE)必须检查返回值,失败时 IV 全零 ≠ 安全 - 没有
EVP_CIPHER_CTX_free对应清理,AES_KEY结构体是纯数据,无需释放,但别把它当对象反复 new/delete - 跨平台注意:
openssl/aes.h在某些旧版本 OpenSSL 中路径是openssl\aes.h(Windows),头文件包含需适配
实际加解密中,最易被忽略的是填充与长度校验的耦合关系:解密后必须验证最后一个字节是否等于它自身指示的填充长度,且所有填充字节值一致——否则可能是篡改或密钥错误,不能直接 substr(0, len - pad) 了事。


















