Solución:
Tu punto de partida
PBKDF2-HMAC-SHA-256
número de iteraciones deseadas = 1024
longitud de la sal en bytes = 16
longitud de la clave derivada en bytes = 4096
Algoritmo
Ok, PBKDF2-HMAC-SHA-256 es una opción sólida, aunque si está ejecutando en cualquier CPU moderna de 64 bits, recomendaría encarecidamente PBKDF2-HMAC-SHA-512 en su lugar, porque SHA-512 requiere operaciones de 64 bits que reducen el margen de la ventaja de un atacante basado en GPU, ya que las GPU modernas no funcionan también con 64 bits.
Sal
16 bytes de sal está bien, siempre que sea criptográficamente aleatorio y sea único por contraseña. Las recomendaciones normales están en el rango de 12-24 bytes, y 16 se consideran bastante sólidos.
Salida e iteraciones
4096 bytes de salida son ACTIVAMENTE MALO! SHA-256 tiene un tamaño de salida nativo de 32 bytes. PBKDF2 / RFC2898 establece que en este caso, primero ejecutará 1024 iteraciones para obtener los primeros 32 bytes (más a la izquierda), luego otras 1024 iteraciones para los siguientes 32 bytes, y así sucesivamente 128 veces en total para obtener los 4096 bytes completos de salida que solicitó.
Entonces, hizo 131072 iteraciones en total y obtuvo 4096 bytes de salida. El atacante hará un total de 1024 iteraciones y comparará sus 32 bytes de salida con los primeros 32 bytes (más a la izquierda) de su salida; si son iguales, ¡adivinaron correctamente! ¡Le diste a cada atacante una ventaja de 128: 1!
En cambio, si está satisfecho con la velocidad, debe hacer 131072 iteraciones con 32 bytes de salida; pasará la MISMA cantidad de tiempo que está ahora (¡así que es gratis!), Y sus atacantes necesitarán gastar 128 veces más. tiempo de lo que hacen ahora!
- NOTA: Si cambia a PBKDF2-HMAC-SHA-512, puede usar hasta 64 bytes de salida y cada iteración tomará un poco más de tiempo.
Nunca obtenga más salida para el hash de contraseña que la salida nativa de su función hash, es decir, 20 bytes para SHA-1, 32 para SHA-256, 64 para SHA-512. Opcionalmente, puede almacenar menos, pero no le ahorra ningún cálculo. Recomendaría almacenar al menos 28 bytes de salida (224 bits, que es el doble de 112 bits, la seguridad nominal de 3DES).
Tenga en cuenta que los valores de longitud de salida son salida binaria pura, ANTES de BASE64 o hexifíquelos, si lo hace (personalmente, almacenaría el binario en bruto, usa menos espacio y requiere una conversión menos).
-
8 bytes de sal está bien, porque es globalmente único cuando se genera aleatoriamente, y ese es el propósito de una sal: la singularidad. Demasiado grande no es un problema, por lo que estimar en el lado alto está bien, excepto que desperdicia un poco de almacenamiento.
-
32 bytes Sería bueno para un longitud de clave derivada (la mayoría de los algoritmos de hash generarán entre 16 y 64 bytes, donde 64 es simplemente excesivo). Su valor de 4096 es definitivamente exagerado, ¡de hecho espero que haya confundido bytes con bits allí!
-
Las iteraciones son muy simples: tantas como sea posible en su hardware. Si un inicio de sesión puede demorar hasta medio segundo, evalúe cuántas iteraciones puede hacer antes de que pase medio segundo. En 2020,
400 000
es un valor razonable para un servidor de gama baja (las CPU de servidor promedio pueden manejar más iteraciones). -
SHA-256 es un buen algoritmo si tienes que elegir uno. Evite MD5, SHA-1 y cualquier otra cosa con ataques conocidos. Pueden ser seguros para este propósito (incluso MD5), pero los ataques solo mejoran y es mejor que no uses algo que ya está parcialmente roto.
Si está ejecutando un sistema con poca potencia (por ejemplo, Raspberry Pi), es posible que desee considerar un hardware diferente dependiendo de qué tan seguras deberían ser las cosas, o hacer que el inicio de sesión tome más tiempo. Por lo general, el inicio de sesión se realiza solo una vez al día aproximadamente, por lo que esperar 10 segundos puede ser razonable dependiendo de su aplicación.
Mi primera sugerencia es utilizar el mecanismo de almacenamiento de contraseñas predeterminado de su plataforma. Funciones como password_hash de PHP eliminan todas las preocupaciones y complicaciones del almacenamiento de contraseñas.
Suponiendo que no puede hacer eso, le recomiendo usar bcrypt, o tal vez incluso las funciones scrypt más nuevas. bcrypt es más difícil de descifrar cuando se utilizan operaciones paralelas en una GPU. scrypt grava tanto la memoria como la CPU. Esta respuesta explica todo esto con gran detalle.
Suponiendo que está atascado con pbkdf2 por cualquier motivo …
Sal: Según esta respuesta de 2013 de Thomas Pornin, 128 bits o 16 bytes son suficientes. Las recomendaciones de la Crackstation son 192 bits o 24 bytes. Creo que cualquier lugar en ese rango es seguro. Personalmente, iría con los 24 bytes ya que la longitud de la sal (suponiendo que no se cuelgue de generar datos aleatorios) realmente no contribuye al rendimiento del hash. Asegúrese de utilizar un CSPRNG para generar la sal.
Longitud de la contraseña: La respuesta de Thomas Pornin recomienda 12 bytes, Crackstation 24. Una vez más, tendería a elegir el tamaño más grande, pero creo que cualquier cosa en ese rango es seguro.
Iteraciones: El número de iteraciones debe ser tantas como pueda tolerar. Así que empieza a probar el rendimiento del hash. He visto recomendaciones durante 0.05-0.10 segundos, pero creo que son solo estimaciones. Si tiene recursos computacionales de sobra, tal vez pueda ir un poco más alto (demasiado alto ralentizará demasiado la autenticación). Si tiene pocos recursos computacionales, vaya más pequeño.
Resumen:
number of iterations desired = max you can tolerate
length of the salt in bytes = 16-24
length of the derived key in bytes = 12-24