Как рассчитать AES GCM IV для конкретного блока

Сейчас я использую 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. Однако мне все еще нужна способность расшифровывать определенный блок данных. Можно ли рассчитать IV для конкретной позиции/блока GCM и как это сделать?

Упрощенный код, который я использую для расшифровки шифрования, находится здесь:

        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);

Спасибо!


person Vengrovskyi    schedule 28.12.2018    source источник
comment
Можно вычислить IV+счетчик конкретного блока. Однако тег GCM рассчитывается для полных данных.   -  person kelalaka    schedule 28.12.2018
comment
@kelalaka У меня нет доступа к предоставленному сайту, но в любом случае спасибо. Я вижу увеличение размера каждого файла/данных на 16 байт. Интересно, одинакова ли логика расчета IV для режимов CTR и GCM? Потому что метод CalculateIvForOffset(...) с GCM у меня не работает (однако работает для CTR).   -  person Vengrovskyi    schedule 28.12.2018
comment
вас заставляют использовать GCM?   -  person Afshin    schedule 28.12.2018
comment
Не совсем так, в настоящее время NIST закрыт. Счетчик начинается с 1, но IV может быть обработан. см. здесь. Найдите doc где-нибудь еще. См. стр. 13   -  person kelalaka    schedule 28.12.2018
comment
@Afshin в основном ДА.   -  person Vengrovskyi    schedule 28.12.2018
comment
@Vengrovskyi размер тега 16 байт. IV должен быть добавлен перед, а тег должен быть добавлен.   -  person kelalaka    schedule 29.12.2018


Ответы (2)


GCM основан на сочетании режим CTR и шифрование GHASH код аутентификации сообщения. Поэтому, если вы не хотите проверять целостность сообщения (или уже сделали это и можете быть уверены, что с тех пор сообщение не было подделано), вы можете просто проигнорировать тег аутентификации GHASH и расшифровать сообщение так же, как если он был зашифрован с использованием обычного режима CTR.

Одна деталь, о которой следует знать, заключается в том, что GCM использует значение счетчика 0 для генерации тега аутентификации, в то время как последовательность счетчика для фактического ключевого потока шифрования начинается с 1. Таким образом, вы должны иметь возможность использовать тот же код для вычисления значений счетчика, что и для базовый режим CTR, но вам нужно компенсировать результаты на единицу.

person Ilmari Karonen    schedule 30.12.2018

Спасибо за помощь! Да, найдены все ответы из официальной документации. Реализовал мой вариант генерации IV для конкретного блока, используя пример, приведенный в этот пост

person Vengrovskyi    schedule 01.01.2019