使用OpenSSL(C++)解密后如何移除PKCS7填充?
AES-256 CBC解密后填充未移除的解决方法
我正在使用AES 256和OpenSSL解密一个简单的文本文件,文件可正常解密,但输出时仍保留填充内容。请问该库中是否有内置方法可移除填充,仅保留原始内容?
我加密了一行文本“Hello World”,现在进行解密,原始内容的部分内容可正常显示,但末尾仍有本应在解密后移除的乱码填充。
解密代码如下:
void aes_256_decrypt(unsigned char *ciphertext, int cipher_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext) { AES_KEY aes_key; int len; EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv); EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, cipher_len); EVP_DecryptFinal_ex(ctx, plaintext + len, &len); EVP_CIPHER_CTX_free(ctx); }
OpenSSL的EVP接口默认会自动处理PKCS#7填充,问题出在你的代码没有正确计算并保存解密后的真实明文长度,导致你可能输出了整个缓冲区的内容,包含了填充部分。
修改方案
分别记录EVP_DecryptUpdate和EVP_DecryptFinal_ex输出的长度,求和得到真实明文长度,只输出该长度范围内的内容即可。
修改后的代码示例:
void aes_256_decrypt(unsigned char *ciphertext, int cipher_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext, int *plain_len) { EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); int update_len = 0; int final_len = 0; // 初始化解密上下文 EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv); // 解密主体数据 EVP_DecryptUpdate(ctx, plaintext, &update_len, ciphertext, cipher_len); // 处理最后一块数据(自动移除填充) EVP_DecryptFinal_ex(ctx, plaintext + update_len, &final_len); // 计算真实明文总长度 *plain_len = update_len + final_len; EVP_CIPHER_CTX_free(ctx); }
使用示例
调用解密函数时传入指针接收真实长度,按该长度输出内容:
unsigned char plaintext[1024]; int plain_len; aes_256_decrypt(ciphertext, cipher_len, key, iv, plaintext, &plain_len); // 仅输出真实长度的明文内容 printf("解密后内容:%.*s\n", plain_len, plaintext);
注意事项
- 加密时需使用PKCS#7填充(OpenSSL默认启用,除非手动关闭)
- 若加密时手动关闭了填充,解密时也要对应关闭,且明文长度必须是AES块大小(16字节)的整数倍
内容的提问来源于stack exchange,提问作者Derec
相关产品推荐
相关产品推荐

