Потоковая передача AES-GCM-HKDF AEAD

Этот документ формально определяет математическую функцию, представленную ключами потоковой передачи AES-GCM-HKDF, закодированными в прототипном формате как type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey .

Это шифрование во многом основано на HRRV15 1 . Для анализа безопасности мы обращаемся к HS20 2 .

Ключ и параметры

Ключи описываются следующими частями (все размеры в этом документе указаны в байтах):

  • \(\mathrm{KeyValue}\)— байтовая строка.
  • \(\mathrm{CiphertextSegmentSize} \in \{1, 2, \ldots, 2^{31}-1\}\).
  • \(\mathrm{DerivedKeySize} \in \{16, 32\}\).
  • \(\mathrm{HkdfHashType} \in \{\mathrm{SHA1}, \mathrm{SHA256}, \mathrm{SHA512}\}\).

Действительные ключи дополнительно удовлетворяют следующим свойствам:

  • \(\mathrm{len}(\mathrm{KeyValue}) \geq \mathrm{DerivedKeySize}\).
  • \(\mathrm{CiphertextSegmentSize} > \mathrm{DerivedKeySize} + 24\) (это эквивалентно \(\mathrm{len}(\mathrm{Header}) + 16\) как будет объяснено позже).

Ключи, которые не удовлетворяют ни одному из этих свойств, отклоняются Tink либо при анализе ключа, либо при создании соответствующего примитива.

Функция шифрования

Чтобы зашифровать сообщение \(\mathrm{Msg}\) с соответствующими данными\(\mathrm{AssociatedData}\), мы создаем заголовок, разбиваем сообщение на сегменты, шифруем каждый сегмент и объединяем зашифрованные сегменты.

Создайте заголовок

Мы выбираем однородную случайную строку \(\mathrm{Salt}\) длины\(\mathrm{DerivedKeySize}\) и однородную случайную строку \(\mathrm{NoncePrefix}\)длины 7.

Затем мы устанавливаем \(\mathrm{Header} := \mathrm{len}(\mathrm{Header}) \| \mathrm{Salt} \| \mathrm{NoncePrefix}\), где длина заголовка кодируется как один байт. Обратите внимание, что \(\mathrm{len}(\mathrm{Header}) \in \{24, 40\}\).

Далее мы используем HKDF 3 с хэш-функцией, заданной \(\mathrm{HkdfHashType}\), и входными данными \(\mathrm{ikm} := \mathrm{KeyValue}\), \(\mathrm{salt} := \mathrm{Salt}\)и \(\mathrm{info} := \mathrm{AssociatedData}\)с выходной длиной \(\mathrm{DerivedKeySize}\). Мы называем результат \(\mathrm{DerivedKey}\).

Разделить сообщение

Сообщение \(\mathrm{Msg}\) далее разбивается на части: \(\mathrm{Msg} = M_0 \| M_1 \| \cdots \| M_{n-1}\).

Их длина выбрана таким образом, чтобы удовлетворить:

  • \(\mathrm{len}(M_0) \in \{0,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{len}(\mathrm{Header}) - \mathrm{16}\}\).
  • Если \(n>1\), то \(\mathrm{len}(M_1), \ldots, \mathrm{len}(M_{n-1}) \in \{1,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{16}\}\).
  • Если \(n>1\), то \(\mathrm{len}(M_{0}), \ldots, \mathrm{len}(M_{n-2})\) должен иметь максимальную длину в соответствии с указанными выше ограничениями.

\(n\) может быть не более \(2^{32}\). В противном случае шифрование не удастся.

Зашифруйте блоки

Чтобы зашифровать сегмент \(M_i\), мы вычисляем \(\mathrm{IV}_i := \mathrm{NoncePrefix} \| \mathrm{i} \| b\), где \(\mathrm{i}\) — это 4 байта в кодировке с прямым порядком байтов, а байт $b$ равен 0x00 если $i < n-1$, и 0x01 в противном случае.

Затем мы шифруем \(M_i\) с помощью AES-GCM 4 , где ключ —\(\mathrm{DerivedKey}\), вектор инициализации — \(\mathrm{IV}_i\), а связанные данные — пустая строка. \(C_i\) является результатом этого шифрования (т.е. объединения \(C\) и \(T\) в разделе 5.2.1.2 связанной ссылки AES-GCM).

Объединение зашифрованных сегментов

Наконец, все сегменты объединяются в \(\mathrm{Header} \| C_0 \| \cdots \| C_{n-1}\), который является окончательным зашифрованным текстом.

Расшифровка

Расшифровка инвертирует шифрование. Мы используем заголовок для получения\(\mathrm{NoncePrefix}\)и расшифровываем каждый сегмент зашифрованного текста индивидуально.

API-интерфейсы могут (и обычно так и делают) разрешать произвольный доступ или доступ к началу файла без проверки конца файла. Это сделано намеренно, поскольку можно расшифровать \(M_i\) из \(C_i\), не расшифровывая все предыдущие и оставшиеся блоки зашифрованного текста.

Однако API должны быть осторожны, чтобы не позволить пользователям путать ошибки конца файла и ошибки расшифровки: в обоих случаях API, вероятно, должен вернуть ошибку, и игнорирование разницы может привести к тому, что злоумышленник сможет эффективно обрезать файлы.

Сериализация и парсинг ключей

Чтобы сериализовать ключ в формате «Tink Proto», мы сначала сопоставляем параметры очевидным образом с прототипом, указанным в aes_gcm_hkdf_streaming.proto . version поля должна быть установлена ​​на 0. Затем мы сериализуем ее, используя обычную сериализацию прототипа, и встраиваем полученную строку в значение поля прототипа KeyData . Мы устанавливаем для поля type_url значение type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey . Затем мы устанавливаем key_material_type в SYMMETRIC и встраиваем его в набор ключей. Обычно мы устанавливаем для output_prefix_type значение RAW . Исключением является то, что если ключ был проанализирован с другим значением, установленным для output_prefix_type , Tink может записать либо RAW , либо предыдущее значение.

Чтобы разобрать ключ, мы обращаем описанный выше процесс в обратном порядке (обычным способом при разборе прото). Поле key_material_type игнорируется. Значение output_prefix_type можно либо игнорировать, либо ключи, у которых output_prefix_type отличается от RAW могут быть отклонены. Ключи, version которых отличается от 0, должны быть отклонены.

Известные вопросы

Ожидается, что реализации вышеуказанной функции шифрования не будут безопасными для вилки. См. Безопасность вилки .

Рекомендации


  1. Хоанг, Рейханитабар, Рогавей, Визар, 2015. Онлайн-шифрование с аутентификацией и его устойчивость к неправильному использованию при повторном использовании. КРИПТО 2015. https://eprint.iacr.org/2015/189

  2. Хоанг, Шен, 2020. Безопасность потокового шифрования в библиотеке Google Tink. https://eprint.iacr.org/2020/1019

  3. RFC 5869. Функция извлечения и расширения ключа на основе HMAC (HKDF). https://www.rfc-editor.org/rfc/rfc5869

  4. НИСТ СП 800-38D. Рекомендации по режимам работы блочного шифрования: режим Галуа/счетчика (GCM) и GMAC. https://csrc.nist.gov/pubs/sp/800/38/d/final