Con PBKDF2, ¿cuál es el tamaño de hash óptimo en bytes? ¿Qué pasa con el tamaño de la sal?

22

Al crear un hash con PBKDF2, le permite al desarrollador elegir el tamaño del hash. ¿Siempre es mejor siempre? Además, ¿qué pasa con el tamaño de la sal al azar? ¿Debería ser el mismo tamaño que el hash?

EDITAR: Particularmente en las contraseñas de hash.

    
pregunta blesh 01.08.2012 - 18:56
fuente

3 respuestas

20

Para la función hash, desea utilizar una función para la cual el tipo de plataforma más eficiente (la que producirá más cálculos de hash por segundo y por dólar) sea la máquina que pretende utilizar (es decir, una PC) . Eso es porque estás en una carrera de armas con el atacante, y el atacante puede comprar otro tipo de hardware para obtener una ventaja sobre ti (como una GPU). La GPU es muy buena en aritmética de 32 bits, pero no en aritmética de 64 bits, mientras que una PC (en modo de 64 bits) será bastante rápida en esta última.

Por lo tanto, use una función hash que se ejecuta en operaciones aritméticas de 64 bits. Esto apunta a SHA-512 .

PBKDF2 es una función de derivación clave : produce una salida de tamaño configurable. Para el hashing de contraseñas, desea que el tamaño sea lo suficientemente grande como para disuadir ataques genéricos de preimagen (es decir, probar contraseñas aleatorias hasta que se encuentre una coincidencia), por lo que esto necesitaría, digamos, al menos 80 bits de salida. Si solo por hacer que la seguridad sea más convincente para los incautos y también para la estética, elija la siguiente potencia de 2: una salida de 128 bits . No es útil ir más allá de eso.

La sal debe ser única , lo más única posible. Una forma fácil de lograr valores únicos de sal es generar sales con un PRNG criptográficamente fuerte : la probabilidad de reutilizar un valor de sal será suficientemente bajo para ser descuidado si estas sales aleatorias son lo suficientemente grandes, y "lo suficientemente grande" significa "128 bits". Por lo tanto, use sales de 128 bits aleatorias .

Personalmente, yo prefiero bcrypt sobre PBKDF2 para el hashing de contraseñas.

    
respondido por el Thomas Pornin 13.01.2013 - 21:16
fuente
9

Según el estándar PBKDF2, el tamaño mínimo recomendado para la sal es de 64 bits, aunque personalmente recomendaría 128 bits o más para un margen de seguridad decente. El tamaño de la sal es independiente de su elección de hash.

En lo que respecta a la seguridad, recomiendo elegir una longitud de clave derivada de al menos del mismo tamaño de salida de sal, con un mínimo de 256 bits. Cualquier tamaño de hash inferior a 256 bits está por debajo del límite de seguridad de la mayoría de las funciones de hash modernas de todos modos.

Elegir una longitud de clave derivada que sea menor que la longitud de salida de la función hash tiene poco sentido, a menos que estés usando la clave para un cifrado de bloque que no pueda manejar una clave de ese tamaño.

En términos de seguridad óptima, sugeriría SHA-512 como PRF, con una clave derivada de 512 bits, un salt de 128 bits y tantas iteraciones como su situación lo justifique.

    
respondido por el Polynomial 01.08.2012 - 21:32
fuente
4

En caso de que su plataforma de elección sea .NET, hay un artículo de OWASP específicamente dedicado a sus Rfc2898DeriveBytes class . Nota concreta (énfasis mío):

  

La implementación incorporada de .NET de Rfc2898DeriveBytes limita al usuario   a una función psudorandom: HMAC con SHA-1 . Esto es aceptable en   La mayoría de los escenarios de hoy, pero en el futuro, un hashing más complejo.   la función puede ser requerida.

     

Usando PBKDF2 para el almacenamiento de contraseñas, uno   Nunca debe emitir más bits que el tamaño de la función hash base. Con   PBKDF2-SHA1 esto es 160 bits o 20 bytes . Salida más bits no   hacer el hash más seguro, pero le cuesta al defensor mucho más tiempo   Sin costarle al atacante. Un atacante simplemente comparará el   La primera salida de tamaño de función hash les ahorra tiempo para generar el   reinicio de la salida PBKDF2.

También tienen un ejemplo de código, que ajusté según la guía de las otras respuestas:

public static string Hash(string str)
{
    // Generate the hash, with an automatic 16 byte salt
    using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(str, 16))
    {
        rfc2898DeriveBytes .IterationCount = 10000 // or whatever you can afford
        byte[] hash = rfc2898DeriveBytes.GetBytes(20);
        byte[] salt = rfc2898DeriveBytes.Salt;
        return Convert.ToBase64String(salt) + "|" + Convert.ToBase64String(hash);
    }
}
    
respondido por el Ohad Schneider 13.08.2017 - 13:27
fuente

Lea otras preguntas en las etiquetas