【问题标题】:How to get authentication tag from AES-GCM如何从 AES-GCM 获取身份验证标签
【发布时间】:2016-08-24 01:16:55
【问题描述】:

我正在使用 BouncyCastle 使用 AES256 GCM 算法加密 C# 中的数据。为此,我使用implementation provided by James Tuley。下面是这段代码的sn-p:

public byte[] SimpleEncrypt(byte[] secretMessage, byte[] key, byte[] nonSecretPayload = null)
{
    if (key == null || key.Length != KeyBitSize / 8)
        throw new ArgumentException($"Key needs to be {KeyBitSize} bit!", nameof(key));

    if (secretMessage == null || secretMessage.Length == 0)
        throw new ArgumentException("Secret Message Required!", nameof(secretMessage));

    nonSecretPayload = nonSecretPayload ?? new byte[] { };
        
    byte[] nonce = _csprng.RandomBytes(NonceBitSize / 8);

    var cipher = new GcmBlockCipher(new AesFastEngine());
    var parameters = new AeadParameters(new KeyParameter(key), MacBitSize, nonce, nonSecretPayload);
    cipher.Init(true, parameters);
        
    var cipherText = new byte[cipher.GetOutputSize(secretMessage.Length)];
    int len = cipher.ProcessBytes(secretMessage, 0, secretMessage.Length, cipherText, 0);
    cipher.DoFinal(cipherText, len);
        
    using (var combinedStream = new MemoryStream())
    {
        using (var binaryWriter = new BinaryWriter(combinedStream))
        {
            binaryWriter.Write(nonSecretPayload);
            binaryWriter.Write(nonce);
            binaryWriter.Write(cipherText);
        }

        return combinedStream.ToArray();
    }
}

我需要获取身份验证标签(在RFC 5084 中提到)。它提到身份验证标签是输出的一部分:

AES-GCM 生成两个输出:密文和消息验证码(也称为验证标签)。

我不明白如何从这段代码中获取身份验证标签?谁能帮帮我?

【问题讨论】:

  • 在这个函数的最后,将三部分组合成一个字节数组(成为返回值)。由于nonSecretPayload 是一个传递参数,而cipherText 是根据标准的输出之一,所以我们只剩下nonce。难道在标准中,他们将nonce 称为“身份验证标签”?
  • @dlatikay 我不这么认为:“AES-GCM 有四个输入:AES 密钥、初始化向量 (IV)、纯文本内容和可选的附加认证数据 (AAD)。AES -GCM 生成两个输出:密文和消息身份验证代码(也称为身份验证标签)。为了对 AES-CCM 和 AES-GCM 有一组通用术语,AES-GCM IV 在其余部分被称为随机数这份文件。”。因此,IV 是一个输入,安全标签不是一个输入而是一个输出(或它的一部分)。
  • this 暗示身份验证标签可能已经是密文的一部分,这将导致问题从哪个偏移开始。如果不是,则需要调用一个额外的加密哈希函数来从密文here 生成标签。无论哪种方式,让我们看看那个 BC 库的源代码。
  • @LeonCullens 据我了解,消息验证码只是简单地附加在密文的末尾,并不打算区别对待。您可能想阅读blog.heckel.xyz/2014/03/01/…

标签: c# encryption aes bouncycastle aes-gcm


【解决方案1】:

调用cipher对象的GetMac()函数获取认证标签:

...
cipher.DoFinal(cipherText, len);
var auth_tag =  cipher.GetMac();
...

来源: http://www.bouncycastle.org/docs/docs1.5on/org/bouncycastle/crypto/modes/GCMBlockCipher.html “返回与最后处理的流关联的 MAC 的值” MAC = "消息验证码"

DoFinal() 函数的文档声明“在数据末尾完成附加或验证 MAC 的操作”,这似乎证实了之前的假设,即cipherText 也已经包含 MAC。使用GetMacSize(),您应该能够确定它与cipherText 末尾的偏移量。

【讨论】:

  • 谢谢你,这有效。输出与我在 Forge (javascript) 中的输出相匹配。
  • 我知道问题中没有提到解密,但是请注意这些特定的 api 尝试以自定义方式使用标签,因为在解密时它会抛出异常,如果它没有t 自动验证。
猜你喜欢
  • 2013-07-17
  • 1970-01-01
  • 2015-10-29
  • 2014-07-14
  • 2020-05-29
  • 2017-10-06
  • 2018-08-20
  • 2017-11-09
  • 2022-01-04
相关资源
最近更新 更多