Las aplicaciones OpenSSL deben usarse con cuidado, a menudo tienen valores predeterminados antiguos y posiblemente inseguros, al menos según los estándares contemporáneos.
En este caso, openssl enc
por defecto utiliza un resumen de MD5 ( apps/enc.c
)
if (md && (dgst=EVP_get_digestbyname(md)) == NULL)
{
BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
goto end;
}
if (dgst == NULL)
{
dgst = EVP_md5();
}
La opción -md
"mensaje resumen" se puede usar para establecer esto explícitamente, puede usar cualquier resumen compatible como sha256:
openssl enc -md sha256 -e -aes256 -in infile.txt -out outfile.enc -pass pass:foo
Algunas de sus afirmaciones son correctas, pero no se aplican aquí, específicamente porque un atacante no sabe el resultado del resumen, no se aplica un ataque de colisión.
Encontrar una colisión solo es útil a veces, por ejemplo, cuando la salida MD5 se utiliza como una firma o comprobación de integridad. Un ataque de colisión requiere que tengas una salida de hash para trabajar.
En este caso, MD5 se está utilizando como una función de derivación de claves . Para eso, lo que suele ser más interesante es resistencia a la preimagen : dado un resumen, podría elaborar una entrada (p. Ej., Contraseña) ) Eso lo generaría. MD5 tiene una resistencia a la preimagen buena pero imperfecta, ~ 123 bits en lugar de los 128 previstos, consulte RFC6151 .
Dado solo un archivo cifrado, si la tarea del atacante es recuperar los datos cifrados, entonces debe descubrir la clave simétrica (clave + IV) utilizada para cifrar. Esta clave también es un compendio que puede calcular a partir de una frase de contraseña que puede descubrir en su lugar (una sal, si se usa, está disponible en el archivo).
El atacante no conoce la contraseña o la clave (resumen de salt / contraseña), cualquiera de las dos lo hará: ¿cuál es más barato de encontrar? Lo que podría ayudar a un atacante es si la salida de MD5 está sesgada, pero no lo es, por lo que sé.
(Estrictamente puede haber dos escenarios: recuperar la contraseña para probar algo, no necesariamente acceder a los datos cifrados, o solo recuperar la clave para acceder a los datos cifrados.)
Los dos ataques obvios son:
- fuerza bruta de todo el espacio clave (cifrado simétrico), si la salida KDF (hash / digest) está sesgada, entonces será más pequeña de lo que debería ser, lo que puede ayudar al atacante
- fuerza bruta el espacio de la contraseña, si la entrada fue elegida por un humano, entonces será más pequeño que el espacio de la clave (la sal eliminará los ataques precalculados,
enc
usa una sal aleatoria por defecto)
Idealmente, queremos un buen KDF sin sesgo, una salida al menos tan grande como la entropía de entrada esperada, emparejada con el tamaño de clave de cifrado simétrico y costosa para que el ataque # 2 no ofrezca un atajo.
Usar un compendio como MD5 con una salida corta (salida de 128 bits) como KDF significa que la clave utilizada para realizar el cifrado es solo de 128 bits, y en este caso no es tan larga como su frase de contraseña requerida (~ 160 bits, 62 ^ 26). También tenga en cuenta el tamaño de la clave de cifrado simétrico que se utilizará, lo ideal sería que coincidan.
El mayor problema aquí no es el uso potencialmente problemático de MD5, es que el KDF que openssl enc
los usos son "baratos", específicamente solo usa una ronda una , lo que hace que los ataques de fuerza bruta en las contraseñas sean el mejor ataque ( apps/enc.c
, línea # 569):
EVP_BytesToKey(cipher,dgst,sptr,
(unsigned char *)str,
strlen(str),1,key,iv);
El sexto parámetro de EVP_BytesToKey
(codificado en 1) es la cuenta, diseñada para frenar a un atacante (o no, en este caso). Lo que debería ser usado en su lugar es una función de estiramiento de teclas robusta y costosa como bcrypt o scrypt.