AEAD de streaming AES-GCM-HKDF

Este documento define formalmente a função matemática representada pelas chaves de streaming AES-GCM-HKDF, codificadas no formato proto como type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey.

Essa criptografia é baseada em HRRV151. Para a análise de segurança, consulte a HS202.

Chave e parâmetros

As chaves são descritas pelas seguintes partes (todos os tamanhos neste documento estão em bytes):

  • \(\mathrm{KeyValue}\), uma string de bytes.
  • \(\mathrm{CiphertextSegmentSize} \in \{1, 2, \ldots, 2^{31}-1\}\).
  • \(\mathrm{DerivedKeySize} \in \{16, 32\}\).
  • \(\mathrm{HkdfHashType} \in \{\mathrm{SHA1}, \mathrm{SHA256}, \mathrm{SHA512}\}\).

Além disso, as chaves válidas atendem às seguintes propriedades:

  • \(\mathrm{len}(\mathrm{KeyValue}) \geq \mathrm{DerivedKeySize}\).
  • \(\mathrm{CiphertextSegmentSize} > \mathrm{DerivedKeySize} + 24\) (é igual a \(\mathrm{len}(\mathrm{Header}) + 16\) , conforme explicado mais adiante).

As chaves que não atendem a nenhuma dessas propriedades são rejeitadas pelo Tink, quando a chave é analisada ou quando a primitiva correspondente é criada.

Função de criptografia

Para criptografar uma mensagem \(\mathrm{Msg}\) com dados associados \(\mathrm{AssociatedData}\), criamos um cabeçalho, dividimos a mensagem em segmentos, criptografamos cada um deles e concatenamos os segmentos criptografados.

Criar o cabeçalho

Escolhemos uma string aleatória uniforme \(\mathrm{Salt}\) de comprimento \(\mathrm{DerivedKeySize}\) e uma string aleatória uniforme \(\mathrm{NoncePrefix}\) de comprimento 7.

Em seguida, definimos \(\mathrm{Header} := \mathrm{len}(\mathrm{Header}) \| \mathrm{Salt} \| \mathrm{NoncePrefix}\), em que o comprimento do cabeçalho é codificado como um único byte. Observe que \(\mathrm{len}(\mathrm{Header}) \in \{24, 40\}\).

Em seguida, usamos HKDF3 com a função hash fornecida por \(\mathrm{HkdfHashType}\) e as entradas \(\mathrm{ikm} := \mathrm{KeyValue}\), \(\mathrm{salt} := \mathrm{Salt}\)e \(\mathrm{info} := \mathrm{AssociatedData}\), com comprimento de saída \(\mathrm{DerivedKeySize}\). Chamamos o resultado de \(\mathrm{DerivedKey}\).

Dividir a mensagem

A mensagem \(\mathrm{Msg}\) é dividida em partes: \(\mathrm{Msg} = M_0 \| M_1 \| \cdots \| M_{n-1}\).

As durações são escolhidas para atender a:

  • \(\mathrm{len}(M_0) \in \{0,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{len}(\mathrm{Header}) - \mathrm{16}\}\).
  • Se \(n>1\), então \(\mathrm{len}(M_1), \ldots, \mathrm{len}(M_{n-1}) \in \{1,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{16}\}\).
  • Se \(n>1\), então \(\mathrm{len}(M_{0}), \ldots, \mathrm{len}(M_{n-2})\) precisa ter o comprimento máximo de acordo com as restrições acima.

\(n\) pode ter no máximo \(2^{32}\). Caso contrário, a criptografia falha.

Criptografar os blocos

Para criptografar o segmento \(M_i\), calculamos \(\mathrm{IV}_i := \mathrm{NoncePrefix} \| \mathrm{i} \| b\), em que \(\mathrm{i}\) é de 4 bytes na codificação big-endian e o byte $b$ é 0x00 se $i < n-1$ e 0x01, caso contrário.

Em seguida, criptografamos \(M_i\) usando AES-GCM4, em que a chave é \(\mathrm{DerivedKey}\), o vetor de inicialização é \(\mathrm{IV}_i\)e os dados associados são a string vazia. \(C_i\) é o resultado dessa criptografia, ou seja, a concatenação de \(C\) e \(T\) na seção 5.2.1.2 da referência AES-GCM vinculada.

Concatenar os segmentos criptografados

Por fim, todos os segmentos são concatenados como \(\mathrm{Header} \| C_0 \| \cdots \| C_{n-1}\), que é o texto criptografado final.

Descriptografia

A descriptografia inverte a criptografia. Usamos o cabeçalho para receber \(\mathrm{NoncePrefix}\)e descriptografar cada segmento de texto criptografado individualmente.

As APIs podem (e normalmente permitem) acesso aleatório ou acesso ao início de um arquivo sem inspecionar o final dele. Isso é intencional, já que é possível descriptografar \(M_i\) de \(C_i\), sem descriptografar todos os blocos de texto criptografado anteriores e restantes.

No entanto, as APIs precisam ter cuidado para não permitir que os usuários confundam erros de fim de arquivo e de descriptografia: em ambos os casos, a API provavelmente precisa retornar um erro, e ignorar a diferença pode fazer com que um invasor consiga truncar arquivos.

Serialização e análise de chaves

Para serializar uma chave no formato "Tink Proto", primeiro mapeamos os parâmetros da maneira óbvia para o proto fornecido em aes_gcm_hkdf_streaming.proto. O campo version precisa ser definido como 0. Em seguida, serializamos isso usando a serialização de proto normal e incorporamos a string resultante no valor do campo de um proto KeyData. Definimos o campo type_url como type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey. Em seguida, definimos key_material_type como SYMMETRIC e incorporamos isso a um conjunto de chaves. Normalmente, definimos o output_prefix_type como RAW. A exceção é que, se a chave tiver sido analisada com um valor diferente definido para output_prefix_type, o Tink poderá gravar RAW ou o valor anterior.

Para analisar uma chave, invertemos o processo acima (da maneira usual ao analisar protos). O campo key_material_type é ignorado. O valor de output_prefix_type pode ser ignorado, ou chaves que têm output_prefix_type diferente de RAW podem ser rejeitadas. As chaves com um version diferente de 0 precisam ser rejeitadas.

Problemas conhecidos

As implementações da função de criptografia acima não são consideradas seguras para fork. Consulte Segurança de bifurcação.

Referências


  1. Hoang, Reyhanitabar, Rogaway, Vizar, 2015. Criptografia autenticada on-line e resistência a uso indevido de uso de valores de uso único. CRYPTO 2015. https://eprint.iacr.org/2015/189 

  2. Hoang, Shen, 2020. Segurança da criptografia de streaming na biblioteca Tink do Google. https://eprint.iacr.org/2020/1019 

  3. RFC 5869. Função de derivação de chaves (HKDF) com extração e expansão com base em HMAC. https://www.rfc-editor.org/rfc/rfc5869 

  4. NIST SP 800-38D. Recomendação para modos de operação de cifra de bloco: modo Galois/Counter (GCM) e GMAC. https://csrc.nist.gov/pubs/sp/800/38/d/final