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

使用C# AES-GCM解密WhatsApp Flow数据时遇Nonce尺寸错误

问题:C#中AES-GCM解密WhatsApp Flow数据时Nonce尺寸无效错误

我在使用C#的AES-GCM加密算法解密WhatsApp Flow数据时遇到了问题,负责解密AES密钥和流程数据的Decryptor类代码如下:

public class Decryptor
{
    public static DecryptedRequest DecryptRequest(EncryptedRequest body, string privatePem, string passphrase)
    {
        Log.Information("Decrypting request with body: {Bodyinitial_vector}", body.initial_vector);

        byte[] encryptedAesKey = Convert.FromBase64String(body?.encrypted_aes_key);
        byte[] encryptedFlowData = Convert.FromBase64String(body?.encrypted_flow_data);
        byte[] initialVector = Convert.FromBase64String(body?.initial_vector);

        byte[] decryptedAesKey;
        try
        {
            // Decrypt AES key using private key
            using (var rsa = CreateRsaPrivateKey(privatePem, passphrase))
            {
                decryptedAesKey = rsa.Decrypt(encryptedAesKey, RSAEncryptionPadding.OaepSHA256);
                Log.Information("Decrypted AES Key: {decryptedAesKey}", decryptedAesKey);
            }
        }
        catch (Exception ex)
        {
            throw new FlowEndpointException(421, "Failed to decrypt the request. Please verify your private key.");
        }

        const int TAG_LENGTH = 16;
        byte[] flowDataBuffer = encryptedFlowData;
        byte[] initialVectorBuffer = initialVector;
        byte[] encryptedFlowDataBody = flowDataBuffer[..^TAG_LENGTH];
        byte[] encryptedFlowDataTag = flowDataBuffer[^TAG_LENGTH..];

        byte[] decryptedData;
        try
        {
            using (var aesGcm = new AesGcm(decryptedAesKey))
            {
                decryptedData = new byte[encryptedFlowDataBody.Length];
                aesGcm.Decrypt(initialVectorBuffer, encryptedFlowDataBody, decryptedData, encryptedFlowDataTag);
            }
        }
        catch (CryptographicException ex)
        {
            Log.Error("Decryption failed: {ErrorMessage}", ex.Message);
            throw new FlowEndpointException(400, "Failed to decrypt the request.");
        }

        string decryptedJSONString = Encoding.UTF8.GetString(decryptedData);
        return new DecryptedRequest
        {
            DecryptedBody = decryptedJSONString,
            AesKeyBuffer = decryptedAesKey,
            InitialVectorBuffer = initialVectorBuffer
        };
    }
}

解密在以下代码段失败:

using (var aesGcm = new AesGcm(decryptedAesKey))
{
    decryptedData = new byte[encryptedFlowDataBody.Length];
    aesGcm.Decrypt(initialVectorBuffer, encryptedFlowDataBody, decryptedData, encryptedFlowDataTag);
}

报错信息为:

System.ArgumentException: The specified nonce is not a valid size for this algorithm. (Parameter 'nonce')

我已确认initialVector已正确完成Base64解码并按预期传入,但错误仍提示nonce尺寸无效。

我尝试解密的加密数据如下:

{
    "encrypted_flow_data": "33oaKOMa2tsRCuh7g6JNsFzVB5icbm4dLq3sgrRXImxChcGOKWaTEZycsv/Tgg/jB/7cxQWH9D8HvJFkCc78X/avxOtEj0KbF+TuFKG28xO/HMR3A4rpzSyD37UAJy3eSmQ5CHZV7NOOMteJQNAOZQ3YEpcG/BcH8mo2iOQa2EA/8g==",
    "encrypted_aes_key": "NQBgEO5GMMXVHsRx0oDb+0MeTYPnHDZM2yJBG0CeaJ2VqN9ennPnLKknbVgpfRm7GfGSxsPHvO9sZeNs/SXlmYIoasDXw3pgKVjhPq3BOk93Fkfjs8bwBhDP763RCgO5IsOSgCqvNeGxeXxyM2BLr8rUAwoE74FYRLa6dxg5RGEUpGJjKLU8VZmBDbXanhPmy6+iVcLEE79rZLsA0+kU7IZ44eeR7PpvqiDCcrnjME/uCF24+3g+iVjsgcL5lA5DdhUQnfPnkjLTiC+x/NPp7ev3e7nP+PzTLQOxnnihjggRfYHUzklp9laVLAQoSQh7vvyKJUPyCv9BRhEmR7BJVQ==",
    "initial_vector": "Vs37z73b5OiBJ5hMV0kyUQ=="
}

预期解密结果为:

{
    "data": {
        "farmer_select": "1"
    },
    "flow_token": "TEST",
    "screen": "DEMO_SCREEN",
    "action": "data_exchange",
    "version": "3.0"
}

请问导致nonce尺寸无效的原因是什么,该如何解决?


问题原因与解决方案

原因分析

C#中的AesGcm类对nonce长度有严格规范:

  • 无论使用128位、192位还是256位AES密钥,AesGcm默认要求nonce为12字节(96位)
  • 你提供的initial_vector经Base64解码后长度为16字节,不符合该要求,因此抛出尺寸无效异常。

解决方案

结合WhatsApp Flow的加密规范,可按以下步骤修复:

  1. 截取有效nonce部分:将解码后的初始向量截取前12字节作为AES-GCM所需的nonce,修改代码:
    byte[] initialVectorBuffer = initialVector.Take(12).ToArray();
    
  2. 验证AES密钥长度:确保RSA解密得到的AES密钥是16字节(128位)、24字节(192位)或32字节(256位),AesGcm仅支持这三种密钥长度。
  3. 核对密文拆分逻辑:你当前将密文末尾16字节作为GCM标签的逻辑是正确的(GCM标准标签长度为16字节),无需调整。

验证修改

修改后重新运行解密流程,若仍报错,需检查:

  • RSA解密得到的AES密钥是否正确(可通过打印密钥字节长度或对比官方示例验证)
  • 是否严格遵循WhatsApp Flow的加密文档中关于nonce、密文、标签的组装规则

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 23:52:34