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

AES-CMAC实现中多次调用EVP_EncryptUpdate结果异常求助

AES-128 CMAC中EVP_EncryptUpdate多次调用失效的原因及解决方法

问题核心

CMAC的计算逻辑要求逐块处理并维护中间异或状态,而EVP_EncryptUpdate是为CBC/GCM等标准流式加密模式设计的接口,它内部会缓存不足块大小的数据,不会暴露每一块的加密结果——这就是导致多次调用结果异常的根本原因。

原因拆解

根据RFC4493的CMAC流程:

  1. 生成子密钥K1、K2;
  2. 对前n-1个完整块,每块加密后与中间CMAC值异或;
  3. 最后一块若为完整块,异或K1后加密;若为不完整块,补位后异或K2再加密;
  4. 最终加密输出即为CMAC值。

当你单次传入N*块大小的缓冲区时,EVP_EncryptUpdate会一次性输出所有块的加密结果,你可以按CMAC逻辑逐块处理异或;但多次调用时,EVP_EncryptUpdate会把不足16字节(AES-128块大小)的数据存在内部上下文,不会输出,导致你无法按CMAC要求及时处理每一块的异或操作,中间状态出错。

正确实现方式

放弃依赖EVP_EncryptUpdate的流式缓存,手动控制分块和中间状态:

  • 初始化EVP加密上下文(用ECB模式,因为CMAC的块加密是ECB方式);
  • 处理前n-1个完整块:
    unsigned char intermediate_cmac[16] = {0};
    unsigned char temp_block[16];
    unsigned char encrypted_block[16];
    int out_len;
    
    for (int i = 0; i < num_full_blocks; i++) {
        // 当前块与中间CMAC值异或
        for (int j = 0; j < 16; j++) {
            temp_block[j] = input[i*16 + j] ^ intermediate_cmac[j];
        }
        // 加密异或后的块
        EVP_EncryptUpdate(ctx, encrypted_block, &out_len, temp_block, 16);
        // 更新中间CMAC值为加密结果
        memcpy(intermediate_cmac, encrypted_block, 16);
    }
    
  • 处理最后一块:
    unsigned char final_block[16] = {0};
    int remaining = input_len % 16;
    memcpy(final_block, input + num_full_blocks*16, remaining);
    
    if (remaining == 0) {
        // 完整块,异或K1
        for (int j = 0; j < 16; j++) {
            final_block[j] ^= K1[j];
        }
    } else {
        // 不完整块,补位后异或K2
        final_block[remaining] = 0x80;
        for (int j = 0; j < 16; j++) {
            final_block[j] ^= K2[j];
        }
    }
    // 最后一次异或加密
    for (int j = 0; j < 16; j++) {
        final_block[j] ^= intermediate_cmac[j];
    }
    EVP_EncryptUpdate(ctx, cmac_result, &out_len, final_block, 16);
    

关键提示

  • CMAC的块处理逻辑是加密(当前块 XOR 中间状态),而非简单加密所有块后再处理,这和标准流式加密模式完全不同;
  • 必须用ECB模式初始化EVP上下文,因为CMAC的每个块加密都是独立的,不需要IV或链式状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 09:47:00