2009-10-07 17 views
20

Se me ha pedido que implemente algunos cambios/actualizaciones en un sitio de intranet; hacer que sea 'a prueba de futuro' como lo llaman.Cómo actualizar un esquema de almacenamiento de contraseñas (algoritmo hash de cambio)

Encontramos que las contraseñas son hash utilizando el algoritmo MD5. (el sistema ha estado presente desde 2001, por lo que era adecuado en el momento).
Ahora nos gustaría actualizar el algoritmo de hashing a uno más fuerte (BCrypt-hash o SHA-256).

Obviamente no sabemos las contraseñas en texto plano-y la creación de una nueva contraseña de la base de usuarios es no es una opción*).

Por lo tanto, mi pregunta es:

¿Cuál es la forma aceptada para cambiar hash-algoritmo sin tener acceso a las contraseñas en texto plano?
La mejor solución sería una solución completamente 'detrás de escena'.

*) intentamos; Intenté convencerlos, utilizamos el argumento de "contraseña de edad", intentamos sobornarlos con café, intentamos sobornarlos con pastel, etc. etc. Pero es , no es una opción.

actualización
que estaba esperando algún tipo de solución automagic para resolver el problema, pero al parecer no hay otras opciones que simplemente 'esperar a que el usuario inicie sesión, a continuación, convertir'.

Bueno, al menos ahora no hay otra solución disponible.

Respuesta

24

Primero, agregue un campo al DB para identificar si la contraseña usa MD5 o el nuevo algoritmo.

para todas las contraseñas siguen usando MD5:

- En el proceso de inicio de sesión, que se verifica su contraseña introducida de un usuario: almacenar temporalmente la contraseña presentado del usuario en la memoria (sin problema de seguridad aquí, ya que ya está en la memoria en algún lugar) y hacer el habitual hash MD5 & comparar con el hash almacenado;

- Si se proporcionó la contraseña correcta (coincide con el hash existente), ejecute la contraseña almacenada temporalmente mediante el nuevo algoritmo, almacene ese valor, actualice el nuevo campo para identificar que esta contraseña se actualizó al nuevo algoritmo.

(Por supuesto que sólo podría utilizar el nuevo algoritmo para nuevos usuarios/contraseñas nuevas.)

3

Agregue el campo passwordChange datetime a la base de datos.

Todo contraseña establecida antes del día X, revise el uso de MD5

Todas las contraseñas establecidas tras día X, revise el uso de Bcrypt o lo que sea.

+0

Y cambie la contraseña del usuario cuando inicia sesión desde MD5 a BCrypt. – Dennis

3

Puede almacenar, ya sea en el campo hash mismo (por ejemplo, "MD5: d41d8cd98f00b204e9800998ecf8427e") o en otra columna, qué algoritmo se utilizó para crear ese hash. Luego, deberá modificar el proceso de inicio de sesión para usar el algoritmo correcto al verificar la contraseña. Naturalmente, cualquier contraseña nueva será hash utilizando el nuevo algoritmo. Afortunadamente, las contraseñas finalmente caducan, y con el tiempo todos los hash MD5 se eliminarán.

+1

También podría hacer que el proceso de inicio de sesión "actualice" la contraseña al nuevo algoritmo hash, suponiendo que tiene acceso a la contraseña de texto simple en ese momento. – Craig

+1

D'oh! Por supuesto que puedes, y deberías. –

3

Dado que usted no sabe la contraseña en texto plano, tal vez debería crear un campo que indica la versión de encriptación (como PasswordVersion bit default 0)

La próxima vez que el usuario intenta iniciar sesión, revise contraseñas encriptado utilizando la versión actual algoritmo, al igual lo haces hoy Si coincide, hash nuevamente y actualiza el campo PasswordVersion.

Esperemos que no necesite una columna PasswordVersion mayor que bit. =)

+0

"Espero que no necesites una columna de PasswordVersion más grande que un bit" me hizo sonreír (+1) – Jacco

+0

Realmente, no hagas la suposición de que esta vez lo hiciste bien. Use 'byte' para su PasswordVersion. –

+1

¿Solo 8 intentos para hacerlo bien? Conviértalo en un 'int' y obtendrá suficiente espacio para hacer su propio error ... =) –

3

debe cambiar su contraseña de base de datos para almacenar 3 artículos:

  1. Un algoritmo de identificación.
  2. Una cadena de sal aleatoria elegida por el servidor cuando primero calcula y almacena el hash de contraseña.
  3. El hash de la concatenación de salt + contraseña utilizando el algoritmo especificado.

Por supuesto, estos sólo pueden ser almacenados juntos en un campo de texto con un delimitador:

"SHA256: esto-es-sal: esto-es-hash-value"

Ahora

convertir entradas que existentes en un valor con sal vacío y el viejo algoritmo

"MD5 :: this-is-la-edad-md5-hash-sin-sal"

Ahora tiene suficiente información para verificar todas las entradas de contraseñas existentes, pero también puede verificar nuevas entradas (ya que sabe qué función hash se usó). Puede convertir las antiguas entradas al algoritmo nuevo la próxima vez que los usuarios de inicio de sesión existente ya que tendrá su contraseña disponible durante este proceso:

  1. Si su base de datos indica que están utilizando el algoritmo antiguo sin sal, primero verificar la contraseña a la antigua, verificando que el hash MD5 de la contraseña coincida. Si no, rechace el inicio de sesión.
  2. Si se verificó la contraseña, haga que el servidor elija una cadena de sal aleatoria, calcule el hash SHA256 de la contraseña sal +, y reemplace la entrada de la tabla de contraseña por una nueva que especifique el nuevo algoritmo, sal y hash.
  3. Cuando el usuario inicie sesión de nuevo, verá que está utilizando el nuevo algoritmo, por lo tanto, calcule el hash de la contraseña salt + y verifique que coincida con el hash almacenado.

Finalmente, después de que este sistema haya estado funcionando durante un tiempo adecuado, puede deshabilitar las cuentas que no se han convertido (si lo desea).

La adición de una cadena de sal aleatoria única para cada entrada hace que este esquema sea mucho más resistente a los ataques de diccionario utilizando tablas de arcoiris.

+0

el viejo esquema MD5 ya usó el hashing correcto. – Jacco

+0

No estoy seguro de entender su comentario, a menos que con "uso de hash adecuado" quiera decir que ya agregó un valor de sal antes de hash la contraseña con MD5. Si es así, el esquema para la actualización aún funciona, solo tiene que tener en cuenta la sal al verificar con MD5 también. –

5

No estoy del todo seguro acerca de esta opción, ya que no soy un experto en criptografía. ¡Por favor corrígeme si me equivoco en algún momento aquí!

Creo que Dave P. tiene claramente la mejor opción.

... pero. Existe una solución automágica: hash los hash más antiguos. Es decir, tome los hash actuales y péguelos nuevamente con un algoritmo más fuerte. Tenga en cuenta que, por lo que yo entiendo, aquí no se obtiene ninguna seguridad adicional de la longitud de hash, solo la complejidad criptográfica añadida del nuevo algoritmo.

El problema es, por supuesto, que la comprobación de una contraseña tendría que ir a través de ambos hash. Y tendrías que hacer lo mismo para cada nueva contraseña también. Que es, bueno, más o menos tonto. A menos que desee utilizar un esquema similar al que Dave P. explicó para eventualmente graduarse con contraseñas de un solo hash con el nuevo algoritmo hash ... en cuyo caso, ¿por qué molestarse con esto? (De acuerdo, puede usarlo en una llamativa "Seguridad mejorada para todas las contraseñas, ¡aplicada inmediatamente!" - forma en una presentación para trajes corporativos, con una cara relativamente recta ...)

Aún así, es una opción que puede se aplicará de inmediato a todas las contraseñas actuales, sin ninguna fase de migración gradual.

Pero chico, oh chico, alguien va a reírse mucho después de leer ese código. :)

+0

Esto suena como lo que estaba buscando. Pero no estoy seguro de las implicaciones de 'hashing a hash', creo que leí en alguna parte que los resultados podrían no ser óptimos en ciertas condiciones. Pero no sé – Jacco

+1

Esta es una mala idea, porque si hay una colisión en el primer hash, entonces hay una colisión en el algoritmo combinado. Y hay colisiones conocidas en MD5. –

+2

@Richard, ¿por qué importaría una colisión hash en este contexto? –

Cuestiones relacionadas