Mis observaciones son las siguientes:
- Almacenar el valor de
l
no tiene sentido. Debe almacenar n
en su lugar. Debe tener en cuenta que PBKDF2 no produce secuencias diferentes para valores diferentes de l
, sino que extiende la secuencia por más tiempo.
- La generación de 1024 bytes para
k
y 512 bytes para P
parece impar, ya que AES no acepta más de una clave de 256 bits (32 bytes).
- En el paso 5 del cifrado, usted dice que
k
está cifrado usando AES-CBC, pero no menciona cómo se selecciona el IV. Esto no es muy importante aquí, ya que k
no tendrá bloques duplicados, pero es una buena práctica usar el modo de cifrado correctamente.
- En el paso 5 del descifrado, nuevamente mencionas AES-CBC sin especificar el IV. Esto es fundamental: la selección incorrecta de la IV puede romper completamente el sistema.
- No proporciona autenticidad en el archivo ni en los metadatos almacenados. Esto es realmente importante, porque AES-CBC es maleable (es decir, el texto cifrado se puede modificar de manera que afecte al texto plano, sin necesidad de conocer la clave) y su construcción podría ser particularmente susceptible.
Su construcción general está realmente bien, pero falta los detalles que separan una construcción segura de una débil.
Así es como lo haría:
- sea p la contraseña del usuario.
- deje que kd (clave de datos) sea un valor aleatorio de 128 bits.
- permita que s (sal) sea un valor aleatorio de 128 bits.
- sea c el recuento de iteraciones, por ejemplo, 1,000,000.
- deje que km (clave maestra) y ka (clave de autenticidad) se calculen como dos 16 Byte (128 bits) mitades de PBKDF2 (p, s, c, 32) , es decir, PBKDF2 de la contraseña de usuario y sal, con el recuento de iteraciones definido y una longitud de salida de 32 bytes.
- deje que k'd (clave de datos cifrados) se calcule como AES (k d , k m ) , utilizando AES de 128 bits en modo ECB.
- deje que IV sea el vector de inicialización para usar al cifrar los datos del archivo.
- sea Q (metadatos) los valores concatenados s | c | k ' d | IV .
- sea aQ el registro de autenticidad para Q , definido como H (Q, k a ) , donde H es una función hash criptográfica en una construcción HMAC, por ejemplo HMAC-SHA256.
- almacene Q y aQ en el encabezado del archivo.
Dado que se están utilizando claves de 128 bits, y AES tiene un tamaño de bloque de 128 bits, solo se necesita cifrar un bloque al calcular k'd y, por lo tanto, AES en modo ECB es seguro; la complejidad adicional de usar CBC u otro modo no es necesaria.
Proporcionar un registro de autenticidad para los metadatos ayuda a evitar que un atacante "ajuste" los parámetros necesarios para descifrar el archivo. Lo más importante es que proporciona autenticidad del IV, que es un objetivo primordial para la modificación, ya que si se le asigna un valor, el primer bloque de texto sin formato también se borrará con ese valor al descifrarlo. Esta propiedad es conocida como maleabilidad. Para plaintexts parcialmente conocidos (por ejemplo, estructurados), esto puede tener efectos devastadores.
Debería poder extrapolar el resto del proceso de cifrado y descifrado de archivos desde aquí. Una adición que haría es calcular un hash HMAC de los datos cifrados, luego almacenarlos en el encabezado, para garantizar la autenticidad de los datos cifrados.