Как получить тег аутентификации из AES-GCM

Я использую BouncyCastle для шифрования данных на C # с использованием алгоритма AES256 GCM. Для этого я использую реализацию , предоставленную Джеймсом Тьюли. Ниже приведен фрагмент этого кода:

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 генерирует два вывода: зашифрованный текст и код аутентификации сообщения (также называемый тегом аутентификации).

Я не понимаю, как получить тег аутентификации из этого кода? Может кто-нибудь мне помочь?


person Leon Cullens    schedule 29.04.2016    source источник
comment
В конце этой функции три части объединяются в массив байтов (который становится возвращаемым значением). Поскольку nonSecretPayload является параметром прохода, а cipherText - одним из выходов в соответствии со стандартами, остается nonce. Может быть, в стандарте они ссылаются на nonce как на тег аутентификации?   -  person Cee McSharpface    schedule 01.05.2016
comment
@dlatikay Я так не думаю: AES-GCM имеет четыре входа: ключ AES, вектор инициализации (IV), текстовое содержимое и необязательные дополнительные проверенные данные (AAD). AES-GCM генерирует два вывода: зашифрованный текст и код аутентификации сообщения (также называемый тегом аутентификации). Чтобы иметь общий набор терминов для AES-CCM и AES-GCM, AES-GCM IV в оставшейся части этого документа упоминается как одноразовый номер. Таким образом, IV является входом, а тег безопасности - не входом, а выход (или его часть).   -  person Leon Cullens    schedule 01.05.2016
comment
this намекает, что тег аутентификации может уже быть частью cipherText, что может привести к вопросу, с какого смещения он будет начинаться. Если это не так, необходимо вызвать дополнительную криптографическую хеш-функцию для создания тега из зашифрованного текста здесь В любом случае давайте посмотрим на исходный код этой библиотеки BC.   -  person Cee McSharpface    schedule 01.05.2016
comment
@LeonCullens Насколько я понимаю, код аутентификации сообщения просто добавляется в конец зашифрованного текста и не предназначен для другой обработки. Вы можете прочитать blog.heckel.xyz/2014/03/01/   -  person Leonard Brünings    schedule 01.05.2016


Ответы (1)


Вызовите функцию GetMac() объекта cipher, чтобы получить тег аутентификации:

...
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.

person Cee McSharpface    schedule 01.05.2016
comment
Спасибо, это сработало. Вывод соответствует выводу, который у меня есть в Forge (javascript). - person Leon Cullens; 03.05.2016
comment
Я знаю, что расшифровка не упоминается в вопросе, но просто будьте осторожны с этим конкретным api, пытающимся использовать тег по-своему, потому что при расшифровке он выдаст исключение, если он не проверит автоматически. - person jbtule; 04.05.2016