XAES-256-GCM: AEAD com nonce estendido
(words.filippo.io)- XAES-256-GCM é uma nova especificação de AEAD que usa chave de 256 bits e nonce de 192 bits para tornar o gerenciamento de nonces menos arriscado em APIs de criptografia de alto nível
- O nonce maior permite uma abordagem em que um novo valor é gerado automaticamente pelo CSPRNG do sistema operacional para cada mensagem, visando um risco de colisão na ordem de 2⁻³² em 2⁸⁰ mensagens
- Internamente, é uma construção de nonce estendido que deriva uma chave e um nonce de 96 bits a partir da chave de entrada e do nonce grande, e então usa AES-256-GCM padrão sem modificações
- A implementação de referência em Go cabe em menos de 100 linhas usando apenas
crypto/cipherecrypto/aes, e parte das 3 chamadas de AES-256 por mensagem pode ser pré-computada - Com foco em conformidade com FIPS 140 e compatibilidade com bibliotecas, pode ser usada como candidata para uma API AEAD sem nonce, junto com XChaCha20Poly1305 e AES-GCM-SIV
AEAD com nonce grande para APIs de alto nível
- XAES-256-GCM é um algoritmo de criptografia autenticada com dados adicionais (AEAD) que usa chave de 256 bits e nonce de 192 bits
- O objetivo do projeto se resume a três pontos
- suporte a nonce grande em que a geração aleatória é segura mesmo com uma quantidade de mensagens praticamente ilimitada
- conformidade total e direta com FIPS 140
- implementação fácil sobre bibliotecas criptográficas comuns
- Graças ao nonce grande, é possível criar APIs que leem um novo nonce do CSPRNG do sistema operacional para cada mensagem, sem que o usuário precise calcular diretamente o birthday bound
- Ao priorizar conformidade e compatibilidade, pode ser aplicado onde for necessário AEAD mesmo em ambientes em que outros AEADs com nonce grande sejam difíceis de usar
Uma construção de nonce estendido que reaproveita AES-256-GCM como está
- XAES-256-GCM é uma construção de nonce estendido construída sobre um AEAD existente, como o XChaCha20Poly1305
- A partir da chave de entrada e do nonce de 192 bits, calcula uma chave derivada e um nonce derivado para uso interno com AES-256-GCM
- a chave de entrada e o nonce são
KeN, respectivamente - a chave e o nonce derivados para AES-256-GCM são
KₓeNₓ
- a chave de entrada e o nonce são
Kₓé gerado com chamadas aAES-256ₖe a parte inicial do nonce, e os 96 bits finais do nonce de entrada são usados comoNₓ- São necessárias 3 chamadas a
AES-256ₖpor mensagem- uma delas pode ser pré-computada para uma determinada chave
- as outras duas podem reutilizar o mesmo key schedule
A implementação é curta e pode ser descrita com componentes padrão
- A implementação de referência em Go tem menos de 100 linhas, incluindo a otimização de pré-computação e a maior parte do boilerplate
- A implementação em Go usa apenas
crypto/cipherecrypto/aesda biblioteca padrão - XAES-256-GCM também pode ser descrito com o KDF padrão NIST SP 800-108r1 e o AEAD NIST AES-256-GCM padrão
- o KDF é counter-based KDF
- a PRF é CMAC-AES256
- a chave de entrada é
Kin - o rótulo é o caractere ASCII
X, ou seja,0x58 - o contexto são os primeiros 96 bits do nonce de entrada
- o tamanho do contador é de 16 bits
- o campo opcional
Lé omitido - a saída é uma chave derivada de 256 bits
- A chave derivada e os últimos 96 bits do nonce de entrada são passados para o AES-256-GCM
- Graças à escolha dos parâmetros, ao remover as abstrações de KDF e CMAC, o resultado é apenas um pouco mais lento e mais complexo do que simplesmente chamar AES-256 sobre o contador
- Os mesmos parâmetros também são compatíveis com a API OpenSSL de alto nível
Implementações de terceiros e vetores de teste
- Em uma edição de 2024-06-29, foram adicionadas implementações de terceiros
- A implementação da Web Cryptography API usa uma
CryptoKeyAES-CBC de 256 bits - A especificação inclui vetores de teste para os dois principais caminhos de código
MSB₁(L) = 0MSB₁(L) = 1
- Também são fornecidos vetores de teste acumulados que condensam 10.000 ou 1.000.000 de iterações aleatórias
O abandono de /11 e alternativas
- A ideia anterior usava o nome
XAES-256-GCM/11, mas a especificação final abandonou o/11 - O
/11era uma otimização de desempenho e, como um dos motivos para usar AES-GCM é a conformidade com FIPS 140, alterar o número de rodadas eliminaria essa conformidade - Se a conformidade com FIPS 140 não for um objetivo, há várias alternativas
- AES-GCM-SIV
- construções modernas de AEAD baseadas no core do AES
- A seção Alternatives da especificação compara cada alternativa com o XAES-256-GCM
Seu lugar no Go e em APIs AEAD sem nonce
- XAES-256-GCM busca ser um AEAD seguro, sem firulas, compatível com conformidade e interoperável
- Seu principal caso de uso é o tipo de API de alto nível que se gostaria de adicionar ao Go
- XAES-256-GCM complementa XChaCha20Poly1305 e AES-GCM-SIV, e foi projetado como candidato de implementação para uma hipotética API AEAD sem nonce
- Como não há preferência por adicionar à biblioteca padrão do Go uma construção específica do Go, são necessárias opiniões de mantenedores de outras bibliotecas criptográficas
1 comentários
Opiniões no Hacker News
O design é muito inteligente: por ser baseado em CMAC, consegue derivar a chave com AES-CBC mesmo sem primitivas de nível mais baixo
Do ponto de vista do AES-CBC, dá para ver como começar com
L = AES-CBC-256ₖ(iv = 0¹²⁸, plaintext = 0¹²⁸)[:16], criarK1, criptografarM1eM2para obterKₓe então usarNₓ = N[12:]Dá para pensar no AES-CBC-256 como retornando apenas o primeiro bloco de 128 bits do texto cifrado e descartando o bloco de padding; mesmo que não seja possível desativar o padding, isso só custa mais 3 chamadas AES com a mesma chave do que uma implementação de nível mais baixo, então não é ruim
Uma implementação em JS baseada na WebCrypto API que usa essa característica está em https://github.com/dchest/xaes e também oferece suporte a características de
CryptoKey, como aceitar diretamente umaCryptoKeypara AES-CBC e armazená-la no IndexedDB comextractable=falseNaquele pseudocódigo, metade dos números parece contar bytes e a outra metade bits, e, se você já não conhece o algoritmo, é quase impossível saber qual é qual
Por exemplo,
N[:12]parece 12 bytes, mas0¹²⁸são 16 bytes, eXé o caractere literal'X', ou seja, a sequência de bits01011000, enquantoLé uma variável, não a sequência de bits01001100Parece claro que matemáticos não gostam de notação sem ambiguidades tanto quanto o pessoal de ciência da computação
0¹²⁰10000111são sequências de bits que representam os coeficientes do primeiro polinômio em ordem lexicográfica, entre os polinômios irredutíveis de graubcom o menor número de termos não nulos, para o tamanho de blocobda cifra de bloco subjacente usada pelo CMACNão há nenhuma intenção escondida
Este trabalho permite evitar esse problema facilmente mudando não só o nonce, mas também a chave a cada chamada do AES-GCM
Além disso, se você tem AES-GCM, ele usa apenas AES “comum”, geralmente disponível, e evita novas construções complexas que ainda podem ter pontos fracos
O overhead por mensagem é de dois buffers pequenos que precisam ser criptografados/descriptografados com AES “comum” e um nonce mais longo de 192 bits
[1]: https://frereit.de/aes_gcm/
Parece eliminar a armadilha do AES-GCM puro, em que, ao usar nonces aleatórios, é preciso trocar a chave a cada cerca de 2^32 mensagens
No AES-GCM, uma colisão de nonce é catastrófica e, no mínimo, permite que um atacante assine mensagens arbitrárias
Não é obrigatório usar nonces aleatórios, mas isso costuma ser recomendado, e é bastante inteligente torná-lo compatível com FIPS usando duas primitivas: uma função de derivação de chaves baseada em contador e GCM puro
No AES-GCM padrão, 96 bits não são suficientes para evitar colisões aleatórias, então é preciso usar geração determinística de nonces
Além disso, independentemente de como o nonce foi criado, depois de 2^32 blocos é preciso trocar o nonce ou a chave, porque o contador dá rollover e o próximo bloco passa a usar o mesmo nonce+contador do primeiro bloco
Realmente impressionante. Eu gostaria que isso existisse alguns anos atrás, quando criei meu último sistema de arquivos criptografado
Em implantações de sistemas de arquivos em grande escala, colisões de nonce são uma grande preocupação
2^32 parece grande, mas, em um array na escala de PB gravando a 100k IOPS por segundo e contando com a aleatoriedade de um gerador pseudoaleatório, a chance de colisão é praticamente garantida
[1] https://en.m.wikipedia.org/wiki/CAESAR_Competition
Isso não significa apenas que dois blocos compartilham a mesma chave de criptografia?
Se eu não conheço o texto claro de nenhum dos blocos, não vejo como isso enfraquece a segurança do sistema
Eu gostaria que isso fosse usado em uma variante do age compatível com FIPS para criptografia de arquivos de arquivamento
Em auditorias do setor bancário, o age foi rejeitado para esse uso por usar ChaCha, enquanto a parte de chave pública X25519 do age foi considerada aceitável. Eu achava que X25519 tinha sido aprovado pelo NIST relativamente recentemente
Não tenho experiência com Go, mas, olhando a especificação do age, parece que isso poderia ser encaixado diretamente, e talvez eu tente quando tiver tempo
O nome poderia ser “cage”, significando “compliant actually good encryption”
1: https://github.com/FiloSottile/age
Como não criptógrafo, fico curioso: por que usar um nonce de 192 bits e não de 256 bits?
Não imagino que esses bits extras sejam considerados um custo em aplicações práticas
Seria possível tornar a entrada do CMAC mais longa, mas isso exigiria executar a função de bloco AES-256 mais vezes e também traria problemas incômodos de controle de chave na função de derivação de chaves do CMAC
É parecido com o motivo pelo qual o XChaCha20Poly1305 usa nonces de 192 bits, e o fato de ser consistente com outros AEADs importantes de nonce estendido também é uma vantagem menor
Dizem “risco de colisão de 2⁻³² em 2⁸⁰ mensagens”, mas o fato de o tamanho de bloco do AES ser de apenas 128 bits não causa problemas antes disso?
Como o XAES deriva uma chave grande por mensagem, ele alcança o que muitas vezes é chamado de garantia melhor que o limite de aniversário
Sem mais contexto sobre por que você acha que isso seria um problema, é difícil responder com mais detalhes
“Seguro, entediante, compatível e interoperável”
É o meu tipo favorito de tecnologia
Legal. É bom ver que existe de fato uma construção baseada no NIST
Ainda assim, é uma pena abrir mão de vários recursos que são vantagens da função de derivação de chaves do NIST, como labels e contexto
Entendo que o sacrifício foi feito para minimizar o número de chamadas AES, mas, especialmente para mensagens maiores que algumas centenas de bytes, eu teria priorizado uma separação criptográfica mais forte em vez de economizar algumas chamadas AES
Por fim, nonces GCM aleatórios com mais de 96 bits são definitivamente muito mal compreendidos e oferecem garantias melhores do que nonces de 96 bits[1]
Claro que, se for possível derivar uma nova chave por mensagem, isso é claramente melhor
[1] https://neilmadden.blog/2024/05/23/galois-counter-mode-and-r...