in

¿Es seguro este esquema AEAD de compromiso?

Pregunta

Un código similar al siguiente esquema usando XChaCha20-BLAKE2b fue visto por un criptógrafo hace un tiempo, quien dijo que parecía estar bien y que era una idea interesante. Sin embargo, desde entonces he cambiado ligeramente el diseño y más revisión por pares nunca es algo malo.

Mis preguntas son:

  1. ¿Puedes ver algo potencialmente inseguro en este esquema?
  2. ¿Hay alguna mejora de rendimiento simple que se pueda hacer?

Muchas gracias de antemano y disculpe la extensión de lo siguiente; Siento que el contexto es necesario para entender/justificar el algoritmo.

Motivación

Los AEAD estandarizados, como ChaCha20-Poly1305, AES-GCM y AES-OCB, no se comprometen.

Este término es bastante confuso, con ‘compromiso de clave’, ‘compromiso de mensaje’, ‘compromiso compacto’, ‘clave aleatoria robusta’ y ‘robustez’. Esencialmente, un AEAD comprometido correctamente significa:

  1. La autenticación no puede pasar usando múltiples claves diferentes. [Source]
  2. Como tal, el texto cifrado no se puede descifrar en diferentes textos sin formato usando diferentes claves. [Source]
  3. Es computacionalmente inviable que diferentes textos sin formato y claves den como resultado la misma etiqueta de autenticación. [Source]

Parece lógico que un esquema AEAD tenga esta propiedad para evitar posibles ataques, al igual que las funciones hash modernas (p. ej., BLAKE2 y SHA3) son resistentes a los ataques de extensión de longitud.

Desafortunadamente, actualmente no existen estándares para un esquema AEAD comprometido. Sin embargo, Cifrar-entonces-MAC usando una etiqueta de más de 256 bits con una sola clave o dos claves separadas derivadas de la misma clave es comprometido y recomendado por algunos de los principales autores de investigación de compromiso.

Hacer un esquema AEAD sin compromiso (p. ej., ChaCha20-Poly1305) también se realiza mejor utilizando un MAC resistente a colisiones (p. ej., BLAKE2b-256 o HMAC-SHA256 con clave). Un simple hash de la clave antepuesto al texto cifrado filtra la identidad de la clave. Las alternativas, como el cifrado de ceros, pueden filtrar información a través del tiempo. En este punto, al realizar una verificación por mensaje, también puede usar un AEAD Encrypt-then-MAC. Esta es la misma razón que PASETO (una alternativa a JOSE) usó para v4, que usa XChaCha20-BLAKE2b (creo que Encrypt-then-MAC regular).

Problemas de cifrado y luego MAC

  1. Complica la derivación de claves, ya que debe derivar dos claves separadas para una buena higiene, una para el cifrado y la otra para la autenticación.
  2. Normalmente no permite que el mensaje se cifre en fragmentos. Esto es sensato para grandes cantidades de datos (por ejemplo, menor uso de memoria, detección temprana de daños, etc.).
  3. No hay soporte para datos adicionales/asociados. Esto puede ser útil para cosas como los números de versión.
  4. El implementador debe recordar comparar las etiquetas de autenticación en tiempo constante durante el descifrado.
  5. Es más lento porque requiere 2 pasadas en lugar de 1 o 1,5 pasadas. Por lo tanto, es más como un esquema AEAD resistente al mal uso en la velocidad.
  6. Obtiene una etiqueta más grande ya que desea resistencia a la colisión para que se comprometa. Eso significa almacenar/enviar más datos.

Esquema

Este esquema resuelve 1-4 arriba para el implementador, suponiendo que sea accesible en una biblioteca criptográfica. 5 es inevitable con esta simple construcción, y 6 es lo que quieres que sea comprometido. También proporciona un margen de seguridad ligeramente más alto, aunque innecesario, sobre los AEAD regulares, independientemente del problema del compromiso.

constantes

// These numbers are in bytes
// The encryption key and MAC key are different lengths for extra domain separation

int EncryptionKeySize = 32;
int MacKeySize = 64;
int TagSize = 32;

// These values are different for domain separation
// An example might be "XChaCha20 04/07/22 14:00 Encryption"

byte[] EncryptionContext = UTF8.GetBytes("[Algorithm] [Timestamp] [Purpose]");
byte[] AuthenticationContext = UTF8.GetBytes("[Algorithm] [Timestamp] [Purpose]");

Cifrado

Las entradas son:

Encrypt(byte[] plaintext, byte[] nonce, byte[] key, byte[] additionalData = null)
  • los nonce es el tamaño del nonce para el algoritmo de cifrado (por ejemplo, 192 bits para XChaCha20).
  • los key es de 256 bits porque más grande no es necesario.
  • los additionalData puede ser nulo/vacío.

Paso 1. Dividir el key en una clave de cifrado y una clave de autenticación:

byte[] encryptionKey = BLAKE2b.KeyedHash(message: EncryptionContext || nonce, key, outputLength: EncryptionKeySize);
byte[] macKey = BLAKE2b.KeyedHash(message: AuthenticationContext || nonce, key, outputLength: MacKeySize);

Paso 2. Cifrar el plaintext con encryptionKey:

byte[] ciphertext = XChaCha20.Encrypt(plaintext, nonce, encryptionKey);

Paso 3. Autenticar el additionalData y ciphertext con macKey:

byte[] tag = BLAKE2b.KeyedHash(message: additionalData || ciphertext || LE(additionalData.Length) || LE(ciphertext.Length), macKey, outputLength: TagSize);

Las longitudes son números enteros convertidos a bytes en little-endian.

Paso 4. Devuelve el texto cifrado final:

return ciphertext.Concat(tag);

Descifrado

Las entradas son las mismas excepto plaintext es ahora ciphertextque incluye la etiqueta adjunta.

Paso 1. Igual que para el cifrado.

Paso 2. Calcule la etiqueta de autenticación:

byte[] computedTag = BLAKE2b.KeyedHash(message: additionalData || ciphertext || LE(additionalData.Length) || LE(ciphertext.Length), macKey, outputLength: TagSize);

Paso 3. Compare las etiquetas de autenticación en tiempo constante y anule si no son iguales:

bool validTag = ConstantTime.Equals(tag, computedTag);
if (!validTag) { throw new CryptographicException(); }

Paso 4. De lo contrario, devuelve el mensaje descifrado:

return XChaCha20.Decrypt(ciphertextWithoutTag, nonce, encryptionKey);

Preocupaciones potenciales

Todo menos incluir el nonce en la derivación de claves se realiza de forma estándar. Se siente reutilizar el nonce para múltiples propósitos, pero es una entrada pública.

Tiene sentido incluir la nonce al derivar macKey entonces el nonce está autenticado y el macKey es único cada vez, como en ChaCha20-Poly1305. Sin embargo, aleatorizar los encryptionKey utilizando el nonce es como cifrar con un nonce aleatorio cada vez. Si usa XChaCha20, eso deriva una subclave y un subnonce internamente cada vez.

Esquema modificado

Sin incluir el nonce en el encryptionKey la derivación parece más óptima, por lo que se usa la misma clave con diferentes nonces.

0

¿Te ayudó la respuesta?

Subscribirse
Notificar por
guest
0 Comentarios
Inline Feedbacks
Ver todas las Respuestas

Análisis de algoritmos de selección

¿Es seguro usar un retorno común para múltiples fuentes de alimentación de CC?