Потоковая передача 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}\). Мы называем результат \(k\).

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

Сообщение \(\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\), а связанные данные \(A\) — пустая строка. Мы устанавливаем \(C_i\) как результат этого шифрования (т. е. объединение \(C\) и \(T\) в приведенной выше ссылке).

Объедините сегменты

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

Расшифровка

Расшифровка просто инвертирует шифрование. Мы используем заголовок для получения nonce и расшифровываем каждый сегмент зашифрованного текста индивидуально.

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

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

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

  4. NIST SP 800-38D, Рекомендации по режимам работы блочного шифрования: режим Галуа/счетчика (GCM) и GMAC.