¿Es esta una buena manera de almacenar contraseñas en una aplicación web?

5

Se me ha asignado la tarea de encontrar una mejor manera de almacenar contraseñas y se me ocurrió este algoritmo. Mi comprensión de Crypto no es lo suficientemente fuerte, pero ¿alguien puede verificar esto, por favor?

Entradas: Nombre de usuario Código de acceso

Algoritmo:

Pase el nombre de usuario a través de uuid (RFC 4122) para obtener un nombre de usuario con hash (esto se debe principalmente a generar una cadena de longitud fija para que el DB pueda indexarlo ordenadamente)

Seleccione uuid de la base de datos para obtener la ID.

Salt = md5 (nombre de usuario hash + ID db + contraseña)

Descartar variables de entrada.

sha512 (contraseña, sal, rondas)

Donde las rondas = 2 ^ ((días entre ahora - 1 de enero de 2008)) / 365) * factor (50000 quizás).

Descarte las sugerencias en la cadena resultante sobre sal y rondas (se pueden regenerar).

Almacena la carga útil hash.

Salida:

Una cadena que se va a probar con la cadena almacenada, cambia cada inicio de sesión debido al aumento constante de las rondas.

    
pregunta user13037 13.09.2012 - 21:14
fuente

8 respuestas

16

No hagas esto. Por favor no lo hagas Hará que los que te persigan te odien. Y puede o no ser seguro en absoluto.

Solo usa una biblioteca existente para las contraseñas de hash. Preferiblemente uno que use la biblioteca crypt(3) debajo (dependiendo del idioma, sugeriría uno, pero no indicó un idioma objetivo).

Tu método de generación de sal no es horrible, pero tampoco es genial.

Simplemente apégate a los algoritmos existentes. Existen y se recomiendan por una razón ... No intentes inventar las tuyas solo para ser inteligente. Puede funcionar, pero por lo general no ...

    
respondido por el ircmaxell 13.09.2012 - 23:16
fuente
8

¿El hash de ID de usuario?

  

Pase el nombre de usuario a través de uuid (RFC 4122) para obtener un nombre de usuario con hash (esto se debe principalmente a generar una cadena de longitud fija para que el DB pueda indexarlo ordenadamente)

     

Seleccione uuid de la base de datos para obtener la ID.

Esto no tiene sentido: las bases de datos pueden indexar cadenas de longitud variable sin problemas. De hecho, lo harán mejor que un UUID ya que la mayoría de los nombres de usuario tienen menos de 32 caracteres, por lo que solo tienes:

  • Haciendo su programa más complicado
  • Ampliar sus índices

Sal

  

Salt = md5 (nombre de usuario hash + ID db + contraseña)

¿Por qué? Se supone que la sal es un valor único, por lo que este exceso excesivo y discutible es menos útil que una sal completamente aleatoria. Solo toma algunos datos aleatorios de algún lugar ( /dev/random o lo que sea que tenga Windows) y guárdalos en la base de datos. De todos modos, está buscando la contraseña, por lo que tomar la sal también no lo ralentizará en absoluto.

El hecho de que estés aprovechando estos valores sugiere que realmente no entiendes lo que está sucediendo.

  • Si este valor se almacenó en cualquier lugar, el esquema de hashing de la contraseña se rompe (porque md5(user+id+password) es mucho más fácil de utilizar en la fuerza bruta que PBKDF2-sha512(password, salt, rounds) . Probablemente sepa que es mejor almacenarlo, pero alguien más podrá acceder más tarde y "optimizar" "it ..
  • Si no se almacena en ningún lado, no tiene sentido trocearlo. Solo use user+id+password como la sal directamente.

Rondas dinámicas

  

Donde las rondas = 2 ^ ((días entre ahora - 1 de enero de 2008)) / 365) * factor (50000 quizás).

Entonces, ¿qué pasa cuando lo miras mañana? De repente, el número de rondas es diferente y sus contraseñas no coinciden. Tendrá que almacenar esto en algún lugar, y la base de datos es el lugar más fácil. Además, si su hardware puede admitir un mayor número de rondas, ¿por qué no comenzar con el número más alto que pueda encontrar?

Si desea obtener un nuevo hash cada vez que alguien inicie sesión, simplemente genere un nuevo salt cada vez.

Conclusión

Puede obtener todo lo que desea, sin ninguna de las vulnerabilidades de seguridad, simplemente haciendo las cosas de manera estándar (bcrypt o PBKDF2, con sales aleatorias, y rounds establece el valor más alto que puede manejar).

    
respondido por el Brendan Long 14.09.2012 - 00:36
fuente
6

Hay un defecto muy importante (asumiendo que te refieres al estándar cryptogrpahic salt que necesariamente se almacena en el base de datos):

salt = md5(Hashed Username ++ db_ID ++ Password)

Con las sales normales, se almacenan en la base de datos y es probable que el nombre de usuario se almacene en una columna separada, por lo que si un administrador malintencionado o un inyector de SQL alguna vez se hace con el DB, pueden usar las sales MD5 almacenadas para forzar la fuerza bruta las contraseñas Dado que MD5 es una sal muy débil, a menos que la contraseña sea una entropía muy alta, una GPU puede descifrarla al probar varios miles de millones de contraseñas por segundo [1] .

Sin embargo, es posible que se haya referido a que su base de datos solo almacena username y multi_round_hash_sha512_hash ; específicamente no almacenar el nombre de usuario derivado 'salt' como en el siguiente ejemplo (donde ++ es concatenación):

db_id = uuid(username);
username_derived_salt = md5(username ++ db_id ++ password);
# this salt not stored in DB
multi_round_hash = password;
for(i=0; i < rounds; i++) {
    multi_round_hash = sha512(multi_round_hash ++ username_derived_salt);
}

En ese caso, esto no es un error, aunque es básicamente equivalente a usar un nombre de usuario como un salt con un poco de oscuridad encima.

Además, el uso de un número dinámico de rondas que aumenta con el tiempo parece innecesariamente complicado y no veo el beneficio en comparación con tener un número fijo (por ejemplo, 100 000 rondas; puede elegir aumentar en algún momento). Preveo muchos problemas de implementación (las marcas de tiempo están desalineadas entre los usuarios, por lo que la cantidad de rondas es diferente; un trabajo cron agrega una ronda adicional a los hashes almacenados en cada día; posibles problemas con los usuarios que intentan iniciar sesión alrededor de la medianoche; problemas de horario de verano) . Al menos, almacene la cantidad de rondas con la contraseña de hash y realice una prueba a fondo.

Usar algo como bcrypt / PBKDF parece mucho más sencillo.

    
respondido por el dr jimbob 13.09.2012 - 23:16
fuente
3

Además de las otras buenas respuestas aquí, ya que está usando SHAxxx, puede encontrar interesante que haya hardware que pueda cree rápidamente hash SHA256 como velocidades extraordinarias. Aunque esto no es actualmente una vulnerabilidad de seguridad, bcrypt está hecho por lo que resiste los ataques basados en FPGA.

También su código parece violar al menos una mejores prácticas de criptografía : no invente su propio criptografía código.

La solución preferida es usar bcrypt o PBKDF2

    
respondido por el random65537 14.09.2012 - 02:36
fuente
3

Se ve bien, además de que tu sal no es aleatoria. Realmente lo estás haciendo (innecesariamente) complicado. Simplemente puede usar Bcrypt, lo que hace su vida mucho más fácil en mi humilde opinión.

    
respondido por el Lucas Kauffman 13.09.2012 - 21:50
fuente
1

Siempre se sugiere que se utilice un mecanismo estándar y probado al almacenar contraseñas. Si bien su algoritmo puede ser lo suficientemente seguro, como han sugerido las otras respuestas, puede ser difícil que otros lo sigan en el futuro. Por lo tanto, se han utilizado métodos comunes como el uso de PBKDF2 para crear hashes de contraseñas. enlace este enlace es un recurso excelente que proporciona el código / técnica para almacenar hashes de contraseñas y está disponible para la mayoría de los idiomas comunes. .

    
respondido por el sudhacker 13.09.2012 - 23:58
fuente
0

MD5 es un algoritmo de hash criptográfico diseñado para la velocidad, y por lo tanto es malo para almacenar contraseñas, incluso con un salt. Use algo lento como HMAC con un complejo sal que es aceptablemente más lento. Sí, significa que las operaciones de inicio de sesión serán imperceptiblemente más lentas, pero también significa que cualquier persona que adquiera su base de datos de contraseñas cifradas debe pasar 10 veces más tiempo descifrando las contraseñas, por lo tanto, 10 veces menos. Las contraseñas se expondrán en el caso de un pirateo catastrófico.

    
respondido por el ScaryLooking 22.09.2012 - 00:01
fuente
-1

también si vas a poner sal a tus hashes, creo que deberías usar sha1 en lugar de hash md5 porque se ha encontrado que md5 es inseguro

    
respondido por el Ahmad 13.09.2012 - 23:18
fuente

Lea otras preguntas en las etiquetas