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

如何在OpenSSL中获取AES-CCM解密生成的TAG并返回给客户端

解决AES-CCM解密时返回生成TAG给客户端的问题

看起来你已经把OpenSSL AES-CCM的机制摸得很透彻了——默认流程是预先传入预期TAG,由OpenSSL内部验证并仅在匹配时输出有效明文,但你的需求是要把解密过程中生成的TAG返回给客户端,让客户端自行完成比对。其实只需要调整一下对OpenSSL上下文的控制命令就能实现,我给你梳理具体步骤和代码示例:

核心思路

OpenSSL的EVP接口提供了EVP_CTRL_CCM_GET_TAG命令,用来提取解密过程中计算出来的TAG值,而非像你之前用的EVP_CTRL_CCM_SET_TAG那样传入预期值做验证。这样即使TAG不匹配,你也能拿到生成的TAG,再返回给客户端做比对。

具体实现步骤

  1. 初始化解密上下文:和常规流程一致,创建并初始化EVP_CIPHER_CTX,设置AES-CCM算法、密钥、IV,同时别忘了设置附加数据(AD,如果你的应用用到的话)和明文/密文的长度。
  2. 执行解密操作:调用EVP_DecryptUpdate和EVP_DecryptFinal_ex处理密文,得到明文。这里要注意:即使后续TAG验证失败,EVP_DecryptFinal_ex会返回错误,但我们仍然可以获取生成的TAG,所以不要直接在这个错误点终止流程。
  3. 提取生成的TAG:调用EVP_CIPHER_CTX_ctrl,使用EVP_CTRL_CCM_GET_TAG命令,指定TAG长度,把生成的TAG读取到缓冲区中。
  4. 返回TAG给客户端:将提取到的TAG和明文一起返回给客户端,由客户端用本地存储的TAG进行比对。

代码示例

// 假设已完成上下文初始化:ctx已创建,密钥、IV、AD等已设置
unsigned char plaintext[1024];
int decrypted_len = 0;
int final_len = 0;

// 解密密文
if (!EVP_DecryptUpdate(ctx, plaintext, &decrypted_len, ciphertext, ciphertext_len)) {
    handleErrors();
}

// 完成解密(即使TAG不匹配,这里返回错误,但我们仍能获取TAG)
if (!EVP_DecryptFinal_ex(ctx, plaintext + decrypted_len, &final_len)) {
    // 可以在这里记录TAG不匹配的日志,但不要终止流程
}
decrypted_len += final_len;

// 提取解密生成的TAG(这里假设TAG长度是14字节,和加密时一致)
unsigned char generated_tag[14];
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, 14, generated_tag)) {
    handleErrors();
}

// 现在将plaintext和generated_tag返回给客户端,由客户端比对存储的TAG

关键注意事项

  • TAG长度一致性:确保解密时指定的TAG长度和加密时完全相同(CCM支持4/6/8/10/12/14/16字节),否则提取的TAG会不正确。
  • 安全比对:客户端在比对两个TAG时,一定要使用恒定时间比较算法,避免时序攻击泄露TAG信息。
  • 上下文生命周期:要在EVP_CIPHER_CTX销毁前完成TAG提取,一旦上下文被释放,TAG数据就无法获取了。

结合你提到的e_aes.c第3835行的实现,OpenSSL确实是在解密过程中逐步计算TAG值,EVP_CTRL_CCM_GET_TAG就是把这个计算后的结果拷贝出来,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:30:37