- XAES-256-GCM es una nueva especificación de AEAD que usa una clave de 256 bits y un nonce de 192 bits para hacer menos riesgosa la gestión de nonces en APIs criptográficas de alto nivel
- Un nonce grande permite un enfoque en el que se genera automáticamente un valor nuevo para cada mensaje desde el CSPRNG del sistema operativo, con el objetivo de un riesgo de colisión de alrededor de 2⁻³² en 2⁸⁰ mensajes
- Internamente, es una construcción de nonce extendido que deriva una clave y un nonce de 96 bits a partir de la clave de entrada y del nonce grande, y luego usa AES-256-GCM estándar sin cambios
- La implementación de referencia en Go cabe en menos de 100 líneas usando solo
crypto/cipherycrypto/aes, y de las 3 llamadas a AES-256 por mensaje, algunas pueden precalcularse - Con énfasis en el cumplimiento de FIPS 140 y la compatibilidad con bibliotecas, puede usarse junto con XChaCha20Poly1305 y AES-GCM-SIV como candidata para una API AEAD sin nonce
AEAD de nonce grande para APIs de alto nivel
- XAES-256-GCM es un algoritmo de cifrado autenticado con datos asociados (AEAD) que usa una clave de 256 bits y un nonce de 192 bits
- El objetivo de diseño se resume en tres puntos
- soporte para nonces grandes cuyo uso aleatorio sea seguro incluso con una cantidad de mensajes prácticamente ilimitada
- cumplimiento total y directo de FIPS 140
- implementación sencilla sobre bibliotecas criptográficas comunes
- Gracias al nonce grande, se puede crear una API que lea un nonce nuevo del CSPRNG del sistema operativo para cada mensaje sin que el usuario tenga que calcular por su cuenta el birthday bound
- Al priorizar cumplimiento y compatibilidad, puede aplicarse donde se necesite AEAD incluso en entornos donde sea difícil usar otros AEAD de nonce grande
Una construcción de nonce extendido que reutiliza AES-256-GCM tal cual
- XAES-256-GCM es una construcción de nonce extendido montada sobre un AEAD existente, como XChaCha20Poly1305
- A partir de la clave de entrada y del nonce de 192 bits, calcula una clave derivada y un nonce derivado para el AES-256-GCM interno
- la clave y el nonce de entrada son
K,N - la clave y el nonce derivados para AES-256-GCM son
Kₓ,Nₓ
- la clave y el nonce de entrada son
Kₓse forma con llamadas aAES-256ₖy la parte inicial del nonce, yNₓusa los 96 bits finales del nonce de entrada- Se requieren 3 llamadas a
AES-256ₖpor mensaje- una de ellas puede precalcularse para una clave dada
- las otras dos pueden reutilizar el mismo key schedule
La implementación es corta y puede describirse con componentes estándar
- La implementación de referencia en Go tiene menos de 100 líneas incluso incluyendo la optimización de precálculo y la mayor parte del boilerplate
- La implementación en Go usa solo
crypto/cipherycrypto/aesde la biblioteca estándar - XAES-256-GCM también puede describirse con el KDF estándar NIST SP 800-108r1 y el AEAD estándar NIST AES-256-GCM
- el KDF es un counter-based KDF
- el PRF es CMAC-AES256
- la clave de entrada es
Kin - la etiqueta es el carácter ASCII
X, es decir0x58 - el contexto son los primeros 96 bits del nonce de entrada
- el tamaño del contador es de 16 bits
- el campo opcional
Lse omite - la salida es una clave derivada de 256 bits
- La clave derivada y los últimos 96 bits del nonce de entrada se pasan a AES-256-GCM
- Gracias a la elección de parámetros, al eliminar las abstracciones de KDF y CMAC, es solo un poco más lento y complejo que simplemente llamar a AES-256 sobre un contador
- Los mismos parámetros también están soportados en la API de alto nivel de OpenSSL
Implementaciones de terceros y vectores de prueba
- Al cierre editorial del 2024-06-29 se añadieron implementaciones de terceros
- La implementación de Web Cryptography API usa un
CryptoKeyAES-CBC de 256 bits - La especificación incluye vectores de prueba para dos rutas principales de código
MSB₁(L) = 0MSB₁(L) = 1
- También se ofrecen vectores de prueba acumulados que comprimen 10,000 o 1,000,000 repeticiones aleatorias
El abandono de /11 y las alternativas
- Una idea anterior llevaba el nombre
XAES-256-GCM/11, pero en la especificación final se descartó/11 /11era una optimización de rendimiento y, como una de las razones para usar AES-GCM es el cumplimiento de FIPS 140, cambiar el número de rondas eliminaría ese cumplimiento- Si el cumplimiento de FIPS 140 no es el objetivo, hay varias alternativas
- AES-GCM-SIV
- construcciones AEAD modernas basadas en el núcleo de AES
- La sección Alternatives de la especificación compara cada alternativa con XAES-256-GCM
Su lugar en Go y en una API AEAD sin nonce
- XAES-256-GCM apunta a ser un AEAD seguro, sobrio, compatible con cumplimiento normativo e interoperable
- Su principal caso de uso es el tipo de API de alto nivel que se quisiera añadir a Go
- XAES-256-GCM complementa a XChaCha20Poly1305 y AES-GCM-SIV, y fue diseñado como candidato de implementación para una hipotética API AEAD sin nonce
- Como no se prefiere añadir a la biblioteca estándar de Go una construcción específica de Go, se necesita la opinión de otros mantenedores de bibliotecas criptográficas
1 comentarios
Opiniones de Hacker News
El diseño es muy ingenioso: como está basado en CMAC, puede derivar claves con AES-CBC incluso sin primitivas de bajo nivel
Desde la perspectiva de AES-CBC, puede verse como empezar con
L = AES-CBC-256ₖ(iv = 0¹²⁸, plaintext = 0¹²⁸)[:16]para crearK1, cifrarM1yM2para obtenerKₓ, y luego usarNₓ = N[12:]Se puede considerar que AES-CBC-256 devuelve solo el primer bloque de 128 bits del texto cifrado y descarta el bloque de padding; incluso si no se puede desactivar el padding, no está mal, porque frente a una implementación de bajo nivel solo cuesta 3 llamadas AES adicionales con la misma clave
Una implementación en JS basada en la WebCrypto API que aprovecha esta característica está en https://github.com/dchest/xaes, y también soporta características de
CryptoKey, como aceptar directamente unCryptoKeypara AES-CBC y almacenarlo en IndexedDB conextractable=falseEn ese pseudocódigo, la mitad de los números parecen contar bytes y la otra mitad bits, y si no conoces ya el algoritmo casi no hay forma de saber cuál es cuál
Por ejemplo,
N[:12]parece 12 bytes, pero0¹²⁸son 16 bytes, yXes el carácter real'X', es decir, la cadena de bits01011000, mientras queLes una variable, no la cadena de bits01001100Está claro que a los matemáticos no les gusta la notación no ambigua tanto como a la gente de ciencias de la computación
0¹²⁰10000111es la cadena de bits que representa los coeficientes del primer polinomio en orden lexicográfico, entre los polinomios irreducibles de gradobpara el tamaño de bloquebdel cifrado de bloque subyacente que usa CMAC, con la mínima cantidad de términos distintos de ceroNo hay ninguna intención oculta
Este trabajo permite evitar fácilmente ese problema cambiando no solo el nonce, sino también la clave en cada llamada a AES-GCM
Además, si se tiene AES-GCM, usa solo AES “normal”, que suele estar disponible, y evita una construcción nueva y compleja que quizá todavía tenga debilidades
El overhead por mensaje es de dos buffers pequeños que hay que cifrar/descifrar con AES “normal” y un nonce más largo de 192 bits
[1]: https://frereit.de/aes_gcm/
Parece eliminar la trampa del AES-GCM puro, en la que al usar nonces aleatorios hay que rotar la clave cada unos 2^32 mensajes
En AES-GCM, una colisión de nonce es catastrófica y, como mínimo, permite que un atacante firme mensajes arbitrarios
No es obligatorio usar nonces aleatorios, pero normalmente se recomienda, y es bastante ingenioso que lo hagan compatible con FIPS usando dos primitivas: una función de derivación de claves basada en contador y GCM puro
En AES-GCM estándar, 96 bits no son suficientes para evitar colisiones aleatorias, así que hay que usar generación determinista de nonces
Además, sin importar cómo hayas creado el nonce, después de 2^32 bloques hay que cambiar el nonce o la clave, porque el contador hace rollover y el siguiente bloque usará el mismo nonce+contador que el primer bloque
Es realmente fantástico. Ojalá hubiera existido hace unos años, la última vez que construí un sistema de archivos cifrado
En despliegues de sistemas de archivos a gran escala, las colisiones de nonce son una gran preocupación
2^32 parece mucho, pero si estás escribiendo a 100k IOPS por segundo en un arreglo de varios PB y dependes de la aleatoriedad de un generador seudoaleatorio, la probabilidad de colisión es prácticamente garantizada
[1] https://en.m.wikipedia.org/wiki/CAESAR_Competition
¿No significa simplemente que dos bloques comparten la misma clave de cifrado?
Si no conozco el texto plano de ninguno de los bloques, no veo cómo eso debilita la seguridad del sistema
Me gustaría que esto se usara en una variante de age compatible con FIPS para cifrado de archivos de archivo/almacenamiento
En una auditoría bancaria rechazaron age para este uso porque usa ChaCha, y consideraron aceptable la parte de clave pública X25519 de age. Tenía entendido que X25519 había sido aprobado por NIST hace relativamente poco
No tengo experiencia con Go, pero viendo la especificación de age parece que se podría encajar directamente, y quizá lo intente si tengo tiempo
El nombre podría ser “cage”, por “compliant actually good encryption”
1: https://github.com/FiloSottile/age
Como no criptógrafo, me pregunto por qué se usa un nonce de 192 bits y no uno de 256 bits
No parece que esos bits adicionales vayan a considerarse un costo en aplicaciones prácticas
También se podría hacer más larga la entrada de CMAC, pero eso requeriría ejecutar más veces la función de bloque AES-256 y además se toparía con problemas molestos de control de claves en la función de derivación de claves CMAC
Es similar a la razón por la que XChaCha20Poly1305 usa nonces de 192 bits, y también es una pequeña ventaja que sea consistente con otros AEAD importantes de nonce extendido
Se dice “riesgo de colisión de 2⁻³² con 2⁸⁰ mensajes”, pero ¿no aparecen problemas antes debido a que el tamaño de bloque de AES es de solo 128 bits?
XAES deriva una clave grande por cada mensaje, así que logra lo que suele llamarse una garantía mejor que el límite de cumpleaños
Sin más contexto sobre por qué crees que sería un problema, es difícil responder con más detalle
“Seguro, aburrido, apto para cumplimiento e interoperable”
Mi tipo de tecnología favorita
Bien. Me alegra que exista una construcción basada en NIST en la práctica
Aun así, es una lástima que se renuncie a varias ventajas de la función de derivación de claves de NIST, como etiquetas y contexto
Entiendo que se haya sacrificado eso para minimizar la cantidad de llamadas AES, pero especialmente para mensajes de más de unos cientos de bytes, yo habría priorizado una separación criptográfica más fuerte antes que ahorrar unas pocas llamadas AES
Por último, los nonces GCM aleatorios de más de 96 bits sin duda se malinterpretan mucho y ofrecen mejores garantías que los nonces de 96 bits[1]
Por supuesto, si se puede derivar una clave nueva para cada mensaje, eso es claramente mejor
[1] https://neilmadden.blog/2024/05/23/galois-counter-mode-and-r...