¿Cuáles son las mejores prácticas para encriptar contraseñas almacenadas en MySql usando PhP?

Estoy buscando consejos sobre cómo almacenar contraseñas de forma segura en MySQL usando PHP.

Pasando por alto las limitaciones de PHP en sí, quiero saber más sobre salazón, hash y encriptación de estos chicos malos.

Obviamente, las personas seguirán utilizando contraseñas débiles a menos que se les obligue a hacerlo de otra manera, pero es la forma en que las guardo lo que es importante para mí. Las contraseñas de mis usuarios son mucho más importantes para mí que la base de datos en sí misma y, por lo tanto, quiero mantenerlas de forma tal que sean minuciosas y monótonas para cualquier script kiddie que intente invertir. Obviamente, con la debida diligencia casi cualquier cosa puede ser derrotada, pero no me importaría hacer esto particularmente molesto.

Hay dos escenarios que estamos viendo.

  1. El niño tiene una copia completa de la base de datos.
  2. El niño tiene una copia completa del PHP utilizado para elaborar la contraseña y la base de datos.

Todos y cada uno de los consejos sobre este tema se aprecian graciosamente.

Usa bcrypt . Si alguien tiene la tabla de usuarios de su base de datos, entonces pueden usar la fuerza bruta / tablas de arcoiris / etc al contenido de su corazón. Incluso con sal, si está usando MD5 o algún otro algoritmo de hash rápido (que no están diseñados para resolver este problema, por cierto); es solo una cuestión de tiempo antes de que pueda ser descifrado.

Cualquier algoritmo de hashing bien conocido y ampliamente respaldado va a tener este mismo “defecto” básico (si puede llamarlo así, es realmente por definición). La diferencia es que bcrypt es lento como melaza cuando se realiza la operación de hash, lo que hace que un ataque de fuerza bruta sea mucho menos efectivo.

Para una discusión absolutamente grande sobre los méritos de bcrypt , los peligros de otros enfoques, y la dificultad de la seguridad de contraseñas en general, lea este hilo . Tiene muchos comentarios de mucha gente que saben mucho más sobre este tipo de cosas que yo, y es de esperar que te ayude a entender más sobre los problemas que están en juego.

Suponiendo que está utilizando el nombre de usuario y la contraseña como tokens de autenticación, puede almacenar de forma segura lo siguiente para asegurarse de que los datos no se vean comprometidos.

  • Nombre de usuario (en texto plano)
  • Sal (cadena aleatoria)
  • Salted Hash ( sha1 (nombre de usuario + salt + contraseña))

Usando el esquema, un atacante no puede usar tablas de arcoíris contra usted y las contraseñas no son recuperables por ningún medio (razonable). (Es decir, siempre y cuando su atacante no sea el gobierno)

Aunque el atacante tiene los pares de sal y hash, no es posible usar tablas de arcoiris porque todos los hashes posibles deberán computarse de todos modos, utilizando la sal que se les ha dado, por lo que es un nuevo ataque de fuerza bruta para cada usuario .

Incluso con el código fuente y el atacante no podrá obtener las contraseñas porque la fortaleza / seguridad está en el algoritmo hashing, no en su código.

Combina esto con el uso de bcrypt según la respuesta de Donut y estarás bastante seguro. Es decir:

  • Nombre de usuario (en texto plano)
  • Sal (cadena aleatoria)
  • Salted Hash ( bcrypt (nombre de usuario + salt + contraseña))

Tomando consejos de aquí , para mayor diversión también puedes cambiar dinámicamente tu sal. Por ejemplo, use diferentes sales para nombres de usuario de diferente duración, use la fecha de registro del usuario como sal. Esto hace que incluso si alguien llega a su base de datos, no pueden simplemente generar de nuevo el hash, tienen que calcular una tabla hash para cada sal que usted utilizó.

Si sus usuarios están en Internet, OpenID sería una de sus mejores opciones. http://openid.net/

Si sus usuarios están en su red, ¿puede hacer Integrated Security?

En otras palabras … no almacene sus contraseñas.

Por lo general, las contraseñas “saladas” (como con bcrypt) significan que no se almacena la contraseña en sí, sino solo algo así como

  salt hash(salt with password appended) 

Ahora, si el niño tiene su base de datos (y, por supuesto, el código, no tiene sentido mantener el código en secreto), solo puede adivinar las contraseñas, calcular el hash salado y comparar. Si la función de hash es costosa (como bcrypt), entonces adivinar es costoso también.

Es sencillo

 store(sha256("somesalt" + password)); 

Y nadie podrá revertirlo 🙂

Ver también: https://stackoverflow.com/questions/3897434/password-security-sha1-sha256-or-sha512