使用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的加密规范,可按以下步骤修复:
- 截取有效nonce部分:将解码后的初始向量截取前12字节作为AES-GCM所需的nonce,修改代码:
byte[] initialVectorBuffer = initialVector.Take(12).ToArray(); - 验证AES密钥长度:确保RSA解密得到的AES密钥是16字节(128位)、24字节(192位)或32字节(256位),
AesGcm仅支持这三种密钥长度。 - 核对密文拆分逻辑:你当前将密文末尾16字节作为GCM标签的逻辑是正确的(GCM标准标签长度为16字节),无需调整。
验证修改
修改后重新运行解密流程,若仍报错,需检查:
- RSA解密得到的AES密钥是否正确(可通过打印密钥字节长度或对比官方示例验证)
- 是否严格遵循WhatsApp Flow的加密文档中关于nonce、密文、标签的组装规则
内容的提问来源于stack exchange,提问作者Walter
相关产品推荐
相关产品推荐

