¿De dónde deben provenir los valores de sal hash?

12

Al agregar valores de sal a un valor hash para algo como una contraseña que no se puede almacenar en texto sin formato, ¿cuál es el mejor lugar para obtener los valores de sal? Por contexto, supongamos que esto es para contraseñas en un inicio de sesión de página web.

Morgan Herlocker
fuente
@DevArt, pensé que era más adecuado aquí porque requiere una respuesta muy subjetiva. Se puede extraer un valor de sal desde cualquier lugar, por lo que pregunto "¿Dónde crees que es la ubicación más segura para extraer valores de sal: cliente o servidor?"
Morgan Herlocker

Respuestas:

7

Por lo general, tengo una columna created TIMESTAMPen una tabla de usuario para poder ver cuándo se registró el usuario. No me gusta agregar una columna adicional para Salt, así que uso la columna de marca de tiempo como salt:

SHA1(password + created)
Jonas
fuente
Entonces supongo que cuando el usuario inicia sesión de nuevo, ¿saca la fecha en función del nombre de usuario cuando vuelve a indicar la verificación?
Morgan Herlocker
1
@Prof: Sí, de la misma manera que lo hace si tiene una columna específica para la sal, por lo que no hay diferencia en esa perspectiva.
Jonas
7

¿Importa?

La sal tiene dos propósitos. Hace que sea poco práctico usar tablas grandes de contraseñas prehavadas ("tablas del arco iris") y hace que las contraseñas idénticas se vean diferentes en la lista de hashes. Hacer que las contraseñas idénticas se vean diferentes ayuda a evitar un problema en el que varias personas están usando una contraseña en particular, que presumiblemente es una contraseña débil común.

Por lo tanto, cada cuenta debe tener su propia sal única, y las sales no deben ser demasiado predecibles, en el sentido de que no habrá un grupo de sales que puedan ocurrir. (Si muchos sitios comenzaron en 1 y siguieron contando, los malos podrían construir tablas de arco iris que incluyen sales de bajo número, por ejemplo). No tienen que ser aleatorias en ningún sentido que no sea generalmente impredecible. No son más secretos que el hash en sí mismo, por lo que no necesitan ser específicamente cuestionables.

Use cualquier método conveniente para generar una sal. Si hay muchos valores de sal potenciales (los primeros sistemas Unix frecuentemente usaban dos bytes, para un posible número de 65536) en comparación con el número de cuentas, la asignación semialeatoria casi nunca daría un sal duplicado.

David Thornley
fuente
1
En general, he visto el segundo problema, las contraseñas idénticas que se ven diferentes, abordadas mediante la concatenación del nombre de usuario, la sal y la contraseña y el hash de toda la cadena. Eso elimina la necesidad de generar una sal única por cuenta.
Justin Cave
1
@Justin: interesante, nunca había visto el nombre de usuario utilizado como parte del hash, pero de hecho es una buena manera de agregar algo de entropía. Sin embargo, todavía usaría una sal pseudoaleatoria, solo porque no cuesta mucho generar una.
Matthieu M.
2
@Matthieu Con la desventaja de tener que almacenarlo en algún lugar, y si ambos lados de una transacción lo necesitan, tener que enviarlo también. Con el nombre de usuario, ambas partes ya lo saben.
Matthew Frederick
2
@Justin: en cuyo caso estás usando el nombre de usuario como una sal. Responde a ambos propósitos de la sal: hacer que las tablas del arco iris no sean prácticas y hacer que las contraseñas similares se vean diferentes.
David Thornley
@David: es cierto, puede verlo como el nombre de usuario que se convierte en parte de la sal. Todavía quiero una sal adicional para que el atacante no pueda usar una tabla de arcoíris para encontrar las combinaciones de nombre de usuario / contraseña. Sin una sal explícita, solo está aumentando el tamaño de la cadena que el atacante necesita de la tabla del arco iris por la longitud del nombre de usuario (que probablemente sea corto y sea completamente minúscula o completamente mayúscula). Una sal constante es suficiente para frustrar un ataque de la tabla del arco iris a menos que su sitio sea lo suficientemente grande como para que un atacante genere una tabla del arco iris específica del sitio.
Justin Cave
3

Cada vez que desee almacenar una nueva contraseña (registro, restablecimiento de contraseña, actualización de contraseña), una buena técnica es:

  • generar nueva sal
    • utilizar un generador de números pseudoaleatorio criptográficamente seguro
    • use una sal de tamaño decente: un buen valor es el tamaño de bloque del algoritmo hash subyacente (podría ser SHA-256)
  • generar un nuevo token de contraseña
    • crear una función hmac a partir del algoritmo hash subyacente (podría ser SHA-256) utilizando la sal como clave hmac
    • for i in (0...65536) { password = hmac(password) }
    • El resultado de las aplicaciones iteradas de la función hmac es el token de contraseña
  • almacenar la sal y el token de contraseña
    • no almacene la contraseña original
    • Opcionalmente, almacene el algoritmo hash subyacente y los tramos para descubrir
Yfeldblum
fuente
1

Aproveche el marco. En .NET podría usar el RNGCryptoServoiceProvider ...

        // If salt is not specified, generate it on the fly.
        if (saltBytes == null)
        {
            // Define min and max salt sizes.
            int minSaltSize = 4;
            int maxSaltSize = 8;

            // Generate a random number for the size of the salt.
            Random  random = new Random();
            int saltSize = random.Next(minSaltSize, maxSaltSize);

            // Allocate a byte array, which will hold the salt.
            saltBytes = new byte[saltSize];

            // Initialize a random number generator.
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

            // Fill the salt with cryptographically strong byte values.
            rng.GetNonZeroBytes(saltBytes); 
        }

Otros marcos deberían tener clases similares que pueda aprovechar. Para lograr la aleatoriedad, el software a menudo emplea al usuario en comparación con Randomlo mencionado anteriormente. TrueCrypt utiliza una opción aleatoria para mover un mouse en un área definida para proporcionar sal. Se reduce a sus necesidades específicas y nivel de seguridad; ya que tu sal simplemente podría ser !@#$%.

Aaron McIver
fuente
1

Se genera un servidor salado y se lo asigna a una cuenta de usuario después de su creación. Mejor use alguna API de generación de cifrado disponible con su marco, pero en principio cualquier secuencia servirá.

Por lo general, las cosas se almacenan así:

User
-------------------
ID
Username
PasswordHashWithSalt

Ejemplo:

PasswordHashWithSalt =

A15CD9652D4F4A3FB61A2A422AEAFDF0DEA4E703 j5d58k4b56s8744q


fuente
¿Asignarlo en función de qué? ¿No tiene que provenir de algún valor que permanecerá en su lugar para que pueda replicarse cuando el usuario vuelva a iniciar sesión después de la creación?
Morgan Herlocker
Con "asignar" me refiero a generar una sal por par de nombre de usuario / contraseña (cuenta) y almacenarlo en la base de datos. Cuando necesita iniciar sesión, usa esa sal almacenada para verificar las cosas.
1

Use bcrypt y lea este artículo ya que los hashes normales por sí solos no son una protección seria en estos días.

Considere utilizar el protocolo de contraseña de conocimiento cero SDR que tiene muchas bibliotecas de código abierto y no tiene patentes.

SDR requiere sal y el mejor lugar para conseguirlo es el cliente; cronometra sus pulsaciones de teclas, movimientos del mouse, hash sus variables de entorno, números aleatorios, tiempos de creación de archivos en su carpeta temporal, para que sal al final de una manera impredecible lejos de su servidor. SDR toma la sal, una clave grande, la contraseña de usuario y genera una clave de verificación. No almacena una contraseña, nunca sale de su máquina, pero puede verificar que tengan la contraseña que va con la clave del verificador y la sal. Es inmune al hombre en el medio y los ataques de diccionario. Cifre las claves y la sal en la columna de la base de datos solo para estar seguro.

simbo1905
fuente