security - example - ¿Cómo puede bcrypt tener sales incorporadas?
import bcrypt java (2)
Creo que esa frase debería haberse redactado de la siguiente manera:
bcrypt tiene sales incorporadas en los hashes generados para evitar ataques de tabla de arco iris.
La utilidad bcrypt
sí no parece mantener una lista de sales. Más bien, las sales se generan aleatoriamente y se agregan a la salida de la función para que se recuerden más adelante (según la implementación de Java de bcrypt
). Dicho de otra manera, el "hash" generado por bcrypt
no es solo el hash. Más bien, es el hash y la sal concatenada.
El artículo de Coda Hale "Cómo almacenar una contraseña de forma segura" afirma que:
bcrypt tiene sales incorporadas para evitar ataques a la tabla del arco iris.
Cita este documento , que dice que en la implementación de bcrypt
de bcrypt
:
OpenBSD genera la sal bcrypt de 128 bits de un flujo de claves arcfour (arc4random (3)), sembradas con datos aleatorios que el kernel recopila a partir de los tiempos del dispositivo.
No entiendo cómo esto puede funcionar. En mi concepción de una sal:
- Debe ser diferente para cada contraseña almacenada, de modo que se deba generar una tabla arco iris separada para cada contraseña.
- Debe almacenarse en algún lugar para que sea repetible: cuando un usuario intenta iniciar sesión, tomamos su intento de contraseña, repetimos el mismo procedimiento salt-and-hash que hicimos cuando originalmente almacenamos su contraseña y comparamos
Cuando uso Devise (un administrador de inicio de sesión de Rails) con bcrypt, no hay una columna de sal en la base de datos, por lo que estoy confundido. Si la sal es aleatoria y no se almacena en ninguna parte, ¿cómo podemos repetir de manera confiable el proceso de hash?
En resumen, ¿cómo puede bcrypt tener sales incorporadas ?
Esto es bcrypt:
Generar una sal al azar. Un factor "costo" ha sido preconfigurado. Recoge una contraseña.
Derive una clave de cifrado a partir de la contraseña utilizando el factor de sal y costo. Úsalo para encriptar una cadena conocida. Almacena el costo, la sal y el texto cifrado. Debido a que estos tres elementos tienen una longitud conocida, es fácil concatenarlos y almacenarlos en un solo campo, y poder separarlos más adelante.
Cuando alguien intente autenticar, recupere el costo y la sal almacenados. Derive una clave de la contraseña de entrada, costo y sal. Encripta la misma cadena conocida. Si el texto cifrado generado coincide con el texto cifrado almacenado, la contraseña es una coincidencia.
Bcrypt opera de una manera muy similar a los esquemas más tradicionales basados en algoritmos como PBKDF2. La principal diferencia es su uso de una clave derivada para cifrar texto sin formato conocido; otros esquemas (razonablemente) suponen que la función de derivación de clave es irreversible y almacenan la clave derivada directamente.
Almacenado en la base de datos, un "hash" de bcrypt
podría tener este aspecto:
$ 2a $ 10 $ vI8aWBnW3fID.ZQ4 / zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa
Esto es en realidad tres campos, delimitados por "$":
-
2a
identifica la versión del algoritmobcrypt
que se utilizó. -
10
es el factor de costo; 2 Se utilizan 10 iteraciones de la función de derivación de claves (lo cual no es suficiente, por cierto. Recomendaría un costo de 12 o más). -
vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa
es la sal y el texto cifrado, concatenado y codificado en una Base-64 modificada. Los primeros 22 caracteres se decodifican a un valor de 16 bytes para la sal. Los caracteres restantes son texto cifrado que se comparará para la autenticación.
Este ejemplo está tomado de la documentación para la implementación de ruby de Coda Hale.