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

OpenSSL 3中C语言禁用加密填充无效问题求助

问题排查与解决

1. 核心问题:未校验EVP_CipherFinal_ex返回值

当禁用填充时,AES-CBC要求明文长度必须是块大小的整数倍(AES-128块大小为16字节)。你的明文长度是33字节,不符合要求,所以EVP_CipherFinal_ex会返回0(加密失败),但你的代码没有判断这个返回值,直接将final_len(此时为0)加到总长度里,导致程序看似正常运行,实则加密未完成。

你觉得两种场景下密文一致,只是因为前32字节(两个完整块)的加密结果相同;禁用填充时,ciphertext数组后16字节是未初始化的垃圾数据,只是巧合和启用填充时的最后一块密文看起来一致而已。

2. 禁用填充的前提:明文长度对齐块大小

要让禁用填充生效,必须保证明文长度是16的整数倍。你可以修改明文长度为32字节,或者手动给明文补充字节凑齐块大小(注意是自定义填充,而非OpenSSL自动填充)。

修改后的代码示例

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <openssl/evp.h>

#define ENCRYPT 1
#define DECRYPT 0

int main()
{
    unsigned char key[] = "0123456789ABCDEF";
    unsigned char iv[]  = "1111111111111111";

    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    if (ctx == NULL) {
        printf("Error creating cipher context.\n");
        exit(EXIT_FAILURE);
    }

    if (EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv, ENCRYPT) != 1) {
        printf("Error initializing cipher.\n");
        exit(EXIT_FAILURE);
    }

    if(EVP_CIPHER_CTX_set_padding(ctx, 0)!=1){//禁用填充
        printf("Error disabling padding.\n");
        exit(EXIT_FAILURE);
    }

    // 修改为32字节的明文(16*2,符合块大小要求)
    unsigned char plaintext[] = "This is the plaintext to encryp"; // 长度32
    unsigned char ciphertext[48];

    int update_len, final_len;
    int ciphertext_len=0;

    if (EVP_CipherUpdate(ctx,ciphertext,&update_len,plaintext,strlen(plaintext)) != 1) {
        printf("CipherUpdate failed.\n");
        EVP_CIPHER_CTX_free(ctx);
        exit(EXIT_FAILURE);
    }
    ciphertext_len+=update_len;
    printf("update size: %d\n",ciphertext_len);

    // 校验Final阶段的返回值,捕获填充禁用时的长度错误
    if (EVP_CipherFinal_ex(ctx,ciphertext+ciphertext_len,&final_len) != 1) {
        printf("CipherFinal failed: plaintext length not multiple of block size!\n");
        EVP_CIPHER_CTX_free(ctx);
        exit(EXIT_FAILURE);
    }
    ciphertext_len+=final_len;

    EVP_CIPHER_CTX_free(ctx);

    printf("Ciphertext length = %d\n", ciphertext_len);

    printf("The content inside ciphertext{");
    for(int i = 0; i < ciphertext_len; i++){
        if(i==ciphertext_len-1)
            printf("%02x", ciphertext[i]);
        else
            printf("%02x-", ciphertext[i]);
    }
    printf("}\n");

    return 0;
}

额外说明

  • OpenSSL 3中EVP_CIPHER_CTX_set_padding的调用时机是正确的,必须在EVP_CipherInit_ex之后、EVP_CipherUpdate之前设置。
  • 若必须加密非块倍数长度的数据且禁用填充,需自行手动处理明文对齐(比如添加自定义填充字节,解密时再移除),但这不符合AES-CBC的标准使用规范,仅适用于特殊场景。

内容的提问来源于stack exchange,提问作者FilResto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 19:53:10