You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 02:05:09