Actualmente se dice que MD5 es parcialmente inseguro. Teniendo esto en cuenta, me gustaría saber qué mecanismo utilizar para la protección con contraseña.
Esta pregunta, ¿es "doble hashing" una contraseña menos segura que simplemente hacerlo una vez? sugiere que el hashing varias veces puede ser una buena idea, mientras que ¿Cómo implementar la protección con contraseña para archivos individuales? sugiere usar sal.
Estoy usando PHP Quiero un sistema de cifrado de contraseña rápido y seguro. Hackear una contraseña un millón de veces puede ser más seguro, pero también más lento. ¿Cómo lograr un buen equilibrio entre velocidad y seguridad? Además, preferiría que el resultado tenga un número constante de caracteres.
- El mecanismo de hash debe estar disponible en PHP
- Debe ser seguro
- Puede usar sal (en este caso, ¿son todas las sales igualmente buenas? ¿Hay alguna forma de generar buenas sales?)
Además, ¿debo almacenar dos campos en la base de datos (uno con MD5 y otro con SHA, por ejemplo)? ¿Lo haría más seguro o inseguro?
En caso de que no estuviera lo suficientemente claro, quiero saber qué funciones de hashing usar y cómo elegir una buena sal para tener un mecanismo de protección de contraseña rápido y seguro.
Preguntas relacionadas que no cubren mi pregunta:
¿Cuál es la diferencia entre SHA y MD5 en PHP?
Simple Password Encryption
Métodos seguros de almacenamiento de claves, contraseñas para asp.net
¿Cómo implementaría contraseñas saladas en Tomcat 5.5?
Respuestas:
TL; DR
No hacer
\0
, lo que puede debilitar seriamente la seguridad).Dos
¿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:
(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.
fuente
Una respuesta mucho más corta y segura: no escriba su propio mecanismo de contraseña , use un mecanismo probado.
La mayoría de los programadores simplemente no tienen la experiencia para escribir código criptográfico de forma segura sin introducir vulnerabilidades.
Autocomprobación rápida: ¿qué es el estiramiento de contraseña y cuántas iteraciones debe usar? Si no sabe la respuesta, debe usarla
password_hash()
, ya que el estiramiento de contraseña es ahora una característica crítica de los mecanismos de contraseña debido a CPU mucho más rápidas y al uso de GPU y FPGA para descifrar contraseñas a tasas de miles de millones de conjeturas por segundo (con GPU )Por ejemplo, puede descifrar todas las contraseñas de Windows de 8 caracteres en 6 horas usando 25 GPU instaladas en 5 PC de escritorio. Esto es una fuerza bruta, es decir, enumerar y verificar cada contraseña de Windows de 8 caracteres , incluidos los caracteres especiales, y no es un ataque de diccionario. Eso fue en 2012, a partir de 2018, podría usar menos GPU o agrietarse más rápido con 25 GPU.
También hay muchos ataques de tabla de arco iris en las contraseñas de Windows que se ejecutan en CPU normales y son muy rápidos. Todo esto se debe a que Windows todavía no elimina ni estira sus contraseñas, incluso en Windows 10 : ¡no cometa el mismo error que Microsoft!
Ver también:
password_hash()
ophpass
son la mejor manera de hacerlo.fuente
No almacenaría el hash de contraseña de dos maneras diferentes, porque entonces el sistema es al menos tan débil como el más débil de los algoritmos de hash en uso.
fuente
A partir de PHP 5.5, PHP tiene funciones simples y seguras para cifrar y verificar contraseñas, password_hash () y password_verify ()
Cuando
password_hash()
se usa, genera una sal aleatoria y la incluye en el hash de salida (junto con el costo y el algoritmo utilizados),password_verify()
luego lee ese hash y determina el método de sal y cifrado utilizado, y lo verifica con la contraseña de texto sin formato proporcionada.Proporcionar
PASSWORD_DEFAULT
instrucciones a PHP para que use el algoritmo de hash predeterminado de la versión instalada de PHP. Exactamente qué algoritmo significa que está destinado a cambiar con el tiempo en futuras versiones, por lo que siempre será uno de los algoritmos más fuertes disponibles.El aumento del costo (que por defecto es 10) hace que el hash sea más difícil de aplicar por fuerza bruta, pero también significa que generar hash y verificar contraseñas en su contra será más trabajo para la CPU de su servidor.
Tenga en cuenta que aunque el algoritmo de hash predeterminado puede cambiar, los hashes antiguos continuarán verificándose bien porque el algoritmo utilizado se almacena en el hash y lo
password_verify()
retoma.fuente
Aunque la pregunta ha sido respondida, solo quiero reiterar que las sales utilizadas para el hash deben ser aleatorias y no como la dirección de correo electrónico como se sugiere en la primera respuesta.
Hay más explicaciones disponibles en: http://www.pivotalsecurity.com/blog/password-hashing-salt-should-it-be-random/
fuente
Solo quiero señalar que PHP 5.5 incluye una API de hash de contraseña que proporciona un contenedor
crypt()
. Esta API simplifica significativamente la tarea de hash, verificación y rehash hashes de contraseñas. El autor también ha lanzado un paquete de compatibilidad (en forma de un único archivo password.php que simplementerequire
debe usar), para aquellos que usan PHP 5.3.7 y versiones posteriores y desean usarlo ahora mismo.Solo es compatible con BCRYPT por el momento, pero su objetivo es ampliarlo fácilmente para incluir otras técnicas de hash de contraseña y debido a que la técnica y el costo se almacenan como parte del hash, los cambios en su técnica / costo de hashing preferido no invalidarán los hashes actuales, el marco automáticamente, usará la técnica / costo correcto al validar. También se encarga de generar una sal "segura" si no define explícitamente la suya.
La API expone cuatro funciones:
password_get_info()
- devuelve información sobre el hash dadopassword_hash()
- crea un hash de contraseñapassword_needs_rehash()
- comprueba si el hash dado coincide con las opciones dadas. Útil para verificar si el hash se ajusta a su esquema actual de técnica / costo, lo que le permite volver a repetir si es necesariopassword_verify()
- verifica que una contraseña coincida con un hashPor el momento, estas funciones aceptan las constantes de contraseña PASSWORD_BCRYPT y PASSWORD_DEFAULT, que son sinónimos en este momento, la diferencia es que PASSWORD_DEFAULT "puede cambiar en versiones de PHP más nuevas cuando se admiten algoritmos de hash más nuevos y más fuertes". El uso de PASSWORD_DEFAULT y password_needs_rehash () al iniciar sesión (y volver a escribir si es necesario) debería garantizar que sus hashes sean razonablemente resistentes a los ataques de fuerza bruta con poco o ningún trabajo para usted.
EDITAR: Me acabo de dar cuenta de que esto se menciona brevemente en la respuesta de Robert K. Dejaré esta respuesta aquí, ya que creo que proporciona un poco más de información sobre cómo funciona y la facilidad de uso que proporciona para aquellos que no conocen la seguridad.
fuente
Estoy usando Phpass, que es una clase PHP simple de un archivo que podría implementarse muy fácilmente en casi todos los proyectos PHP. Ver también El H .
Por defecto, utilizó el cifrado más fuerte disponible que se implementa en Phpass, que es
bcrypt
y recurre a otros cifrados hasta MD5 para proporcionar compatibilidad con versiones anteriores de marcos como Wordpress.El hash devuelto podría almacenarse en la base de datos tal como está. El uso de muestra para generar hash es:
Para verificar la contraseña, se puede usar:
fuente
COSAS PARA RECORDAR
Se ha dicho mucho sobre el cifrado de contraseña para PHP, la mayoría de los cuales es un muy buen consejo, pero antes de comenzar el proceso de usar PHP para el cifrado de contraseña, asegúrese de tener lo siguiente implementado o listo para ser implementado.
SERVIDOR
PUERTOS
No importa qué tan buena sea su encriptación si no asegura adecuadamente el servidor que ejecuta PHP y DB, todos sus esfuerzos no valen nada. La mayoría de los servidores funcionan relativamente de la misma manera, tienen puertos asignados para permitirle acceder de forma remota a través de ftp o shell. Asegúrese de cambiar el puerto predeterminado de cualquier conexión remota que tenga activa. Al no hacer esto, en efecto, ha hecho que el atacante haga un paso menos para acceder a su sistema.
NOMBRE DE USUARIO
Por todo lo que es bueno en el mundo, no use el nombre de usuario admin, root o algo similar. Además, si está en un sistema basado en Unix, NO haga accesible el inicio de sesión de la cuenta raíz, siempre debe ser solo sudo.
CONTRASEÑA
Le dice a sus usuarios que hagan buenas contraseñas para evitar ser pirateados, hagan lo mismo. ¿Cuál es el punto de pasar por todo el esfuerzo de cerrar la puerta cuando tienes la puerta trasera abierta de par en par?
BASE DE DATOS
SERVIDOR
Lo ideal es que desee su base de datos y APLICACIÓN en servidores separados. Esto no siempre es posible debido al costo, pero permite cierta seguridad ya que el atacante tendrá que pasar por dos pasos para acceder completamente al sistema.
USUARIO
Siempre haga que su aplicación tenga su propia cuenta para acceder a la base de datos y solo otorgue los privilegios que necesitará.
Luego, tenga una cuenta de usuario separada para usted que no esté almacenada en ningún lugar del servidor, ni siquiera en la aplicación.
Como siempre, NO hagas esta raíz o algo similar.
CONTRASEÑA
Siga las mismas pautas que con todas las buenas contraseñas. Tampoco reutilice la misma contraseña en ninguna cuenta SERVER o DB en el mismo sistema.
PHP
CONTRASEÑA
NUNCA almacene una contraseña en su base de datos, en su lugar almacene el hash y la sal única, explicaré por qué más adelante.
HASHING
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ de la misma manera y compara los dos hashes. Esto significa que, incluso si un atacante obtiene acceso a la base de datos, no sabe cuál es la contraseña, solo el hash resultante. Lo que significa más seguridad para sus usuarios en el peor escenario posible.
Hay un montón de buenas funciones hash por ahí (
password_hash
,hash
, etc ...), pero tiene que seleccionar un algoritmo de hash bueno para el que sea eficaz. (bcrypt y otros similares son algoritmos decentes).Cuando la clave es la velocidad de hashing, cuanto más lenta, más resistente a los ataques de fuerza bruta.
Uno de los errores más comunes en el hash es que los hash no son exclusivos de los usuarios. Esto se debe principalmente a que las sales no se generan de manera única.
SALAZÓN
Las contraseñas siempre deben ser saladas antes del hash. Salar agrega una cadena aleatoria a la contraseña para que contraseñas similares no aparezcan igual en la base de datos. Sin embargo, si la sal no es exclusiva de cada usuario (es decir, usted usa una sal codificada), entonces prácticamente no la tiene. Porque una vez que un atacante descubre una contraseña de sal, tiene la sal para todos ellos.
Cuando cree una sal, asegúrese de que sea única para la contraseña que está salando, luego almacene tanto el hash como la sal completos en su base de datos. Lo que esto hará es lograr que un atacante tenga que romper individualmente cada sal y hachís antes de poder acceder. Esto significa mucho más trabajo y tiempo para el atacante.
USUARIOS QUE CREAN CONTRASEÑAS
Si el usuario está creando una contraseña a través de la interfaz, eso significa que debe enviarse al servidor. Esto abre un problema de seguridad porque eso significa que la contraseña no cifrada se está enviando al servidor y si un atacante puede escuchar y acceder, toda su seguridad en PHP no tiene valor. SIEMPRE transmita los datos SEGURAMENTE, esto se hace a través de SSL, pero tenga cuidado, incluso SSL no es perfecto (el defecto Heartbleed de OpenSSL es un ejemplo de esto).
También haga que el usuario cree una contraseña segura, es simple y siempre debe hacerse, el usuario se lo agradecerá al final.
Finalmente, sin importar las medidas de seguridad que tome, nada es 100% seguro, cuanto más avanzada sea la tecnología para proteger, más avanzados serán los ataques. Pero seguir estos pasos hará que su sitio sea más seguro y mucho menos deseable para los atacantes.
Aquí hay una clase PHP que crea un hash y salt para una contraseña fácilmente
http://git.io/mSJqpw
fuente
Google dice que SHA256 está disponible para PHP.
Definitivamente deberías usar una sal. Recomiendo usar bytes aleatorios (y no limitarse a caracteres y números). Como de costumbre, cuanto más tiempo elija, más seguro, más lento se vuelve. 64 bytes debería estar bien, supongo.
fuente
Al final, el doble hashing, matemáticamente, no proporciona ningún beneficio. En la práctica, sin embargo, es útil para prevenir ataques basados en tablas de arco iris. En otras palabras, no es más beneficioso que el hashing con sal, que requiere mucho menos tiempo de procesador en su aplicación o en su servidor.
fuente
Encontré un tema perfecto sobre este asunto aquí: https://crackstation.net/hashing-security.htm , quería que se beneficiara de él, aquí también está el código fuente que también proporcionó prevención contra ataques basados en el tiempo.
fuente
Por lo general, uso SHA1 y salt con la ID de usuario (o alguna otra información específica del usuario), y a veces también uso un salt constante (por lo que tengo 2 partes de la salt).
SHA1 ahora también se considera algo comprometido, pero en un grado mucho menor que MD5. Al usar una sal (cualquier sal), evitas el uso de una tabla de arco iris genérica para atacar tus hashes (algunas personas incluso han tenido éxito al usar Google como una especie de tabla de arco iris al buscar el hash). Un atacante podría generar una tabla de arco iris usando su sal, por eso debe incluir una sal específica del usuario. De esa manera, tendrán que generar una tabla de arcoíris para todos y cada uno de los registros de su sistema, ¡no solo uno para todo el sistema! Con ese tipo de salazón, incluso el MD5 es decentemente seguro.
fuente
SHA1 y una sal deberían ser suficientes (dependiendo, naturalmente, de si está codificando algo para Fort Knox o un sistema de inicio de sesión para su lista de compras) en el futuro previsible. Si SHA1 no es lo suficientemente bueno para usted, use SHA256 .
La idea de una sal es desequilibrar los resultados del hash, por así decirlo. Se sabe, por ejemplo, que el hash MD5 de una cadena vacía es
d41d8cd98f00b204e9800998ecf8427e
. Entonces, si alguien con una memoria lo suficientemente buena vería ese hash y sabría que es el hash de una cadena vacía. Pero si la cadena está salada (por ejemplo, con la cadena "MY_PERSONAL_SALT
"), el hash para la 'cadena vacía' (es decir, "MY_PERSONAL_SALT
") se convierteaeac2612626724592271634fb14d3ea6
, por lo tanto, no es obvio para rastrear. Lo que estoy tratando de decir, que es mejor usar cualquier sal, de no hacerlo. Por lo tanto, no es demasiado importante saber qué sal usar.En realidad, hay sitios web que hacen exactamente esto : puede alimentarlo con un hash (md5), y escupe un texto sin formato conocido que genera ese hash en particular. Si tuviera acceso a una base de datos que almacena hash md5 simples, sería trivial que ingrese el hash para el administrador de dicho servicio e inicie sesión. Pero, si las contraseñas fueran saladas, dicho servicio se convertiría ineficaz.
Además, el doble hashing generalmente se considera un mal método, ya que disminuye el espacio resultante. Todos los hashes populares son de longitud fija. Por lo tanto, solo puede tener valores finitos de esta longitud fija, y los resultados se vuelven menos variados. Esto podría considerarse como otra forma de salazón, pero no lo recomendaría.
fuente
sha1(sha1($foo))
reduce efectivamente el espacio de salida, porque cualquier colisión de la función interna se convertirá automáticamente en una colisión de la externa. La degradación es lineal, pero sigue siendo una preocupación. Los métodos de hashing iterativos retroalimentan los datos en cada ronda, como$hash = sha1(sha1($salt . $password) . $salt)
. Pero eso todavía no es bueno ... Quédese con PBKDF2 o Bcrypt ...ok en el ajuste necesitamos sal, la sal debe ser única, así que vamos a generarla
también necesitamos el hash que estoy usando sha512 es el mejor y está en php
así que ahora podemos usar estas funciones para generar una contraseña segura
ahora necesitamos guardar en la base de datos nuestro valor de variable $ hash_psw y $ variable de sal
y para autorizar usaremos los mismos pasos ...
Es la mejor manera de proteger las contraseñas de nuestros clientes ...
Ps para los últimos 2 pasos, puede usar su propio algoritmo ... pero asegúrese de que puede generar esta contraseña cifrada en el futuro cuando necesite autorizar al usuario ...
fuente
sha512
(incluso si está salada) se considera ampliamente que no es lo suficientemente buena para la protección con contraseña. (también que RNG no es criptográficamente seguro, por lo que usarlo para generar contraseñas es arriesgado).