如何为特定块计算AES GCM IV

时间:2018-12-28 17:20:05

标签: c# encryption aes bouncycastle aes-gcm

我现在使用AES CTR加密我们的文档。这样做是为了提供对加密文档进行范围请求的能力。使用AES CTR,可以通过以下简单函数来计算特定块的IV:

    private static int AES_BLOCK_SIZE = 16;

    private static ParametersWithIV CalculateIvForOffset(KeyParameter sk, ParametersWithIV iv,  long blockOffset) 
    {
        var ivBI = new BigInteger(1, iv.GetIV());
        var ivForOffsetBi = ivBI.Add(BigInteger.ValueOf(blockOffset/ AES_BLOCK_SIZE));

        var ivForOffsetBA = ivForOffsetBi.ToByteArray();
        ParametersWithIV ivForOffset;
        if (ivForOffsetBA.Length >= AES_BLOCK_SIZE) {
            ivForOffset = new ParametersWithIV(sk, ivForOffsetBA, ivForOffsetBA.Length - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
        } else {
            byte[] ivForOffsetBASized = new byte[AES_BLOCK_SIZE];
            Array.Copy(ivForOffsetBA, 0, ivForOffsetBASized, AES_BLOCK_SIZE
                    - ivForOffsetBA.Length, ivForOffsetBA.Length);
            ivForOffset = new ParametersWithIV(sk, ivForOffsetBASized);/**/
        }

        return ivForOffset;

}

我在应用中使用BouncyCastle。 但是在某些情况下,我需要跟踪文档的完整性。我想为此使用AES GCM。但是我仍然需要能够解密特定的数据块。 是否可以针对GCM的特定位置/块计算IV以及如何执行?

我用于加密解密的简化代码在这里:

        var offset = 0;
        var decryptionSize = 128;
        var file = Hex.Decode("2B7E151628AED2A6ABF7158809CF4F3C12312312312312312312312312312312312391792837012937019238102938012938017230192830192830192830192730129730129830192380192730192730");

        var encryptor = CipherUtilities.GetCipher("AES/GCM/NoPadding");

        var sk = ParameterUtilities.CreateKeyParameter("AES", Hex.Decode("2B7E151628AED2A6ABF7158809CF4F3C"));
        encryptor.Init(true, new ParametersWithIV(sk, Hex.Decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFD0001")));
        var encryptedFile = encryptor.DoFinal(file);

        var decryptor = CipherUtilities.GetCipher("AES/GCM/NoPadding");
        var arrayToDecrypt = encryptedFile.Skip(offset).Take(decryptionSize).ToArray();

        // recalculate initial vector for offset
        var newiv = CalculateIvForOffset(sk, new ParametersWithIV(sk, Hex.Decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFD0001")),offset);
        decryptor.Init(false, newiv);
        var output2 = decryptor.ProcessBytes(arrayToDecrypt, 0, arrayToDecrypt.Length);

谢谢!

2 个答案:

答案 0 :(得分:0)

GCM基于CTR mode加密和GHASH message authentication code的组合。因此,如果您不想验证消息的完整性(或已经进行了验证,并且可以确保从那时起未对消息进行篡改),则可以简单地忽略GHASH身份验证标签并像对消息进行解密一样如果它是使用常规CTR模式加密的。

一个需要注意的细节是,GCM使用计数器值0来生成认证标签,而实际加密密钥流的计数器序列从1开始。因此,您应该能够使用相同的代码来计算计数器值与基本点阅率模式相同,但您需要将结果偏移一。

答案 1 :(得分:0)

感谢您的帮助! 是的,找到了官方documentation的所有答案。 使用this post

中提供的示例为特定块实现了IV生成的变体