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

AES-256-GCM模式下硬编码密文解密失败求助

AES-256-GCM硬编码解密失败的问题排查

第一大坑:IV长度设置与实际传入字节数不匹配

你在加解密函数里都通过EVP_CTRL_GCM_SET_IVLEN强制把IV长度设为16字节,但实际传入的iv数组只有12个有效字节(末尾的0是多余的字符串终止符):

// 代码硬设IV长度为16字节
if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL))
    handleErrors();

// 实际传入的IV仅12个有效字节,末尾0属于画蛇添足
const unsigned char iv[] = { 0xfd, 0xac, 0xc9, 0x0f, 0x36, 0x02, 0xf2, 0xbb, 0x03, 0x9b, 0x05, 0x67, 0 };

这会导致OpenSSL读取超出iv数组范围的栈内存来凑够16字节,而栈内存是随机的,每次运行都不一样:

  • 加密时实际使用的是16字节IV(前12字节固定,后4字节随机)
  • 解密时同样读取16字节IV,后4字节的随机值几乎不可能和加密时一致,直接触发Tag验证失败,解密返回-1。

第二坑:Tag的写入方式存在未定义行为

在EncDecTest中,你用std::string tag(16, '0')初始化Tag,然后强制转换tag.c_str()传给encrypt函数写入Tag:

std::string tag(16, '0');
// ...
k = encrypt(..., (unsigned char*)tag.c_str());

c_str()返回的是只读指针,强制转成可写指针修改属于未定义行为,大概率Tag根本没被正确写入到tag字符串中,你硬编码的tagHard十有八九不是真实的加密Tag。

修复步骤

1. 统一IV长度(二选一即可)

  • 推荐方案:使用GCM标准12字节IV
    删除加解密函数中设置IV长度的代码(GCM默认IV长度就是12字节),同时去掉iv数组末尾多余的0:

    // 删除这行代码
    // if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) handleErrors();
    
    // 修改IV数组,移除末尾的0
    const unsigned char iv[] = { 0xfd, 0xac, 0xc9, 0x0f, 0x36, 0x02, 0xf2, 0xbb, 0x03, 0x9b, 0x05, 0x67 };
    
  • 若坚持使用16字节IV
    补全iv数组到16字节,比如末尾添加4个0:

    // 保留IV长度设置代码
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) handleErrors();
    
    // 补全IV至16字节
    const unsigned char iv[] = { 0xfd, 0xac, 0xc9, 0x0f, 0x36, 0x02, 0xf2, 0xbb, 0x03, 0x9b, 0x05, 0x67, 0x00, 0x00, 0x00, 0x00 };
    

2. 正确处理Tag存储,别再用c_str()

要么使用std::string的data()方法(C++11及以后支持,返回可写指针),要么直接用数组存储Tag:

// 方法1:使用std::string::data()
std::string tag(16, '\0');
k = encrypt(..., (unsigned char*)tag.data());

// 方法2:直接用数组,更省心
unsigned char tag[16] = {0};
k = encrypt(..., tag);

3. 重新获取正确的密文和Tag

修复上述问题后,运行EncDecTest,通过十六进制打印输出真实的密文和Tag(可以写个小工具函数循环打印),再将正确的值硬编码到simpleDecryptionTest中。

额外提醒

  • 二进制数据(IV、密文、Tag)不需要添加字符串终止符0,它们是纯字节流,加了只会导致长度计算错误或读取多余字节。
  • 打印二进制数据务必用十六进制,避免不可打印字符造成的误判,比如写个简单的打印函数:
    void printHex(const unsigned char* data, int len) {
        for(int i=0; i<len; i++) {
            printf("%02X ", data[i]);
        }
        printf("\n");
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 09:23:09