DESCARGO DE RESPONSABILIDAD : Esta respuesta fue escrita en 2008.
Desde entonces, PHP nos ha dado password_hash
y password_verify
, y, desde su introducción, que son la clave hash recomendada y método de comprobación.
Sin embargo, la teoría de la respuesta sigue siendo una buena lectura.
TL; DR
No hacer
- No limite los caracteres que los usuarios pueden ingresar para las contraseñas. Solo los idiotas hacen esto.
- No limite la longitud de una contraseña. Si sus usuarios quieren una oración con supercalifragilisticexpialidocious, no les impida usarla.
- No elimine ni escape HTML y caracteres especiales en la contraseña.
- Nunca almacene la contraseña de su usuario en texto plano.
- Nunca envíe una contraseña por correo electrónico a su usuario, excepto cuando haya perdido la suya, y usted haya enviado una temporal.
- Nunca, nunca registre contraseñas de ninguna manera.
- ¡Nunca hash contraseñas con SHA1 o MD5 o incluso SHA256! Las galletas modernas pueden superar los 60 y 180 mil millones de hashes / segundo (respectivamente).
- No mezcle bcrypt y con la salida sin formato de hash () , use la salida hexadecimal o base64_encode. (Esto se aplica a cualquier entrada que pueda tener un pícaro
\0
, lo que puede debilitar seriamente la seguridad).
Dos
- Usa scrypt cuando puedas; bcrypt si no puedes.
- Use PBKDF2 si no puede usar bcrypt o scrypt, con hash SHA2.
- Restablezca las contraseñas de todos cuando la base de datos se vea comprometida.
- Implemente una longitud mínima razonable de 8-10 caracteres, además requiera al menos 1 letra mayúscula, 1 letra minúscula, un número y un símbolo. Esto mejorará la entropía de la contraseña, lo que a su vez hará que sea más difícil de descifrar. (Consulte la sección "¿Qué hace una buena contraseña?" Para un debate).
¿Por qué las contraseñas hash de todos modos?
El objetivo detrás de las contraseñas hash es simple: evitar el acceso malicioso a las cuentas de los usuarios al comprometer la base de datos. Entonces, el objetivo del hash de contraseñas es disuadir a un pirata informático o pirata informático al costarles demasiado tiempo o dinero para calcular las contraseñas de texto sin formato. Y el tiempo / costo son los mejores elementos de disuasión en su arsenal.
Otra razón por la que desea un hash bueno y robusto en las cuentas de un usuario es para darle tiempo suficiente para cambiar todas las contraseñas en el sistema. Si su base de datos se ve comprometida, necesitará tiempo suficiente para al menos bloquear el sistema, si no cambia cada contraseña en la base de datos.
Jeremiah Grossman, CTO de Whitehat Security, declaró en el blog de White Hat Security después de una reciente recuperación de contraseña que requirió la ruptura de su protección de contraseña por fuerza bruta:
Curiosamente, al vivir esta pesadilla, aprendí MUCHO que no sabía sobre el descifrado de contraseñas, el almacenamiento y la complejidad. He llegado a apreciar por qué el almacenamiento de contraseñas es mucho más importante que la complejidad de las contraseñas. Si no sabe cómo se almacena su contraseña, entonces todo de lo que realmente puede depender es de la complejidad. Esto podría ser de conocimiento común para los profesionales de contraseñas y criptografía, pero para el experto promedio de InfoSec o Web Security, lo dudo mucho.
(El énfasis es mío).
¿Qué hace una buena contraseña de todos modos?
Entropía . (No es que me suscriba completamente al punto de vista de Randall).
En resumen, la entropía es la cantidad de variación dentro de la contraseña. Cuando una contraseña solo tiene letras romanas en minúsculas, solo tiene 26 caracteres. Eso no es mucha variación. Las contraseñas alfanuméricas son mejores, con 36 caracteres. Pero permitir mayúsculas y minúsculas, con símbolos, tiene aproximadamente 96 caracteres. Eso es mucho mejor que solo letras. Un problema es que, para que nuestras contraseñas sean memorables, insertamos patrones, lo que reduce la entropía. ¡Uy!
La entropía de la contraseña se aproxima fácilmente. El uso de la gama completa de caracteres ascii (aproximadamente 96 caracteres que se pueden escribir) produce una entropía de 6.6 por carácter, que con 8 caracteres para una contraseña sigue siendo demasiado baja (52.679 bits de entropía) para seguridad futura. Pero la buena noticia es que las contraseñas más largas y las contraseñas con caracteres Unicode realmente aumentan la entropía de una contraseña y hacen que sea más difícil descifrarla.
Hay una discusión más larga sobre la entropía de contraseñas en el sitio Crypto StackExchange . Una buena búsqueda en Google también arrojará muchos resultados.
En los comentarios que hablé con @popnoodles, quienes señalaron que hacer cumplir una política de contraseña de longitud X con X muchas letras, números, símbolos, etc., en realidad puede reducir la entropía al hacer que el esquema de contraseña sea más predecible. Estoy de acuerdo. La aleatoriedad, lo más aleatoria posible, es siempre la solución más segura pero menos memorable.
Hasta donde he podido decir, crear la mejor contraseña del mundo es un Catch-22. No es memorable, demasiado predecible, demasiado corto, demasiados caracteres Unicode (difícil de escribir en un dispositivo Windows / Mobile), demasiado largo, etc. Ninguna contraseña es lo suficientemente buena para nuestros propósitos, por lo que debemos protegerlos como si fueran estaban en Fort Knox.
Mejores prácticas
Bcrypt y scrypt son las mejores prácticas actuales. Scrypt será mejor que bcrypt a tiempo, pero no ha visto la adopción como estándar por Linux / Unix o por servidores web, y aún no ha publicado revisiones en profundidad de su algoritmo. Pero aún así, el futuro del algoritmo parece prometedor. Si está trabajando con Ruby, hay una gema de scrypt que lo ayudará, y Node.js ahora tiene su propio paquete de scrypt . Puede usar Scrypt en PHP a través de la extensión Scrypt o la extensión Libsodium (ambos están disponibles en PECL).
Le recomiendo leer la documentación de la función cripta si desea comprender cómo usar bcrypt, o encontrar un buen contenedor o usar algo como PHPASS para una implementación más heredada. Recomiendo un mínimo de 12 rondas de bcrypt, si no de 15 a 18.
Cambié de opinión sobre el uso de bcrypt cuando supe que bcrypt solo usa el programa clave de blowfish, con un mecanismo de costo variable. Este último le permite aumentar el costo de la fuerza bruta de una contraseña al aumentar la ya costosa programación clave de blowfish.
Prácticas promedio
Ya casi no puedo imaginar esta situación. PHPASS es compatible con PHP 3.0.18 a 5.3, por lo que es utilizable en casi todas las instalaciones imaginables, y debe usarse si no sabe con certeza que su entorno es compatible con bcrypt.
Pero suponga que no puede usar bcrypt o PHPASS en absoluto. ¿Entonces que?
Pruebe una implementación de PDKBF2 con el número máximo de rondas que su entorno / aplicación / percepción del usuario puede tolerar. El número más bajo que recomendaría es de 2500 rondas. Además, asegúrese de usar hash_hmac () si está disponible para dificultar la reproducción de la operación.
Prácticas futuras
Próximamente en PHP 5.5 es una biblioteca de protección de contraseña completa que abstrae cualquier dolor de trabajo con bcrypt. Si bien la mayoría de nosotros estamos atrapados con PHP 5.2 y 5.3 en los entornos más comunes, especialmente los hosts compartidos, @ircmaxell ha creado una capa de compatibilidad para la próxima API que es compatible con PHP 5.3.7.
Resumen de criptografía y descargo de responsabilidad
La potencia de cálculo requerida para descifrar una contraseña hash no existe. La única forma en que las computadoras pueden "descifrar" una contraseña es recrearla y simular el algoritmo de hash utilizado para protegerla. La velocidad del hash está relacionada linealmente con su capacidad de ser forzado por la fuerza bruta. Peor aún, la mayoría de los algoritmos hash se pueden paralelizar fácilmente para funcionar aún más rápido. Es por eso que los esquemas costosos como bcrypt y scrypt son tan importantes.
No es posible prever todas las amenazas o vías de ataque, por lo que debe hacer su mejor esfuerzo para proteger a sus usuarios por adelantado . Si no lo hace, incluso podría perderse el hecho de que fue atacado hasta que sea demasiado tarde ... y usted es responsable . Para evitar esa situación, actúa paranoico para empezar. Ataque su propio software (internamente) e intente robar credenciales de usuario, o modificar las cuentas de otros usuarios o acceder a sus datos. Si no prueba la seguridad de su sistema, entonces no puede culpar a nadie más que a usted mismo.
Por último: no soy un criptógrafo. Lo que he dicho es mi opinión, pero creo que se basa en el buen sentido común ... y en mucha lectura. Recuerde, sea lo más paranoico posible, haga las cosas tan difíciles de entrometerse como sea posible, y luego, si todavía está preocupado, comuníquese con un hacker de sombrero blanco o un criptógrafo para ver qué dicen sobre su código / sistema.