Esta sección explica las razones que justifican el uso de funciones hash para proteger las contraseñas. También se explica cómo hacerlo de un modo efectivo.
El hash de contraseñas es una de las consideraciones de seguridad más elementales que se deben llevar a la práctica al diseñar una aplicación que acepte contraseñas de los usuarios. Sin hashing, cualquier contraseña que se almacene en la base de datos de la aplicación podrá ser robada si la base de datos se ve comprometida, con lo que inmediatamente no sólo estaría comprometida la aplicación, sino también las cuentas de otros servicios de nuestros usuarios, siempre y cuando no utilicen contraseñas distintas.
Si aplicamos un algoritmo hash a las contraseñas antes de almacenarlas en la base de datos, dificultamos al atacante el determinar la contraseña original, pese a que en un futuro podrá comparar el hash resultanente con la contraseña original.
Sin embargo, es importante tener en cuenta que el hecho de aplicar hash a las contraseñas sólo protege de que se vean comprometidas las contraseñas almacenadas, pero no las proteje necesariamente de ser interceptadas por un código malicioso inyectado en la propia aplicación.
Los algoritmos hash como MD5, SHA1 o SHA256 están diseñados para ser muy rápidos y eficientes. Con las técnicas y equipos modernos, es algo trivial extraer por fuerza bruta la salida de estos algoritmos, para determinar los datos de entrada originales.
Dada la velocidad con que los ordenadores actuales pueden "invertir" estos algoritmos hash, muchos profesionales de la seguridad recomiendan encarecidamente no utilizarlas como funciones hash para contraseñas.
Al aplicar un algoritmo hash, los dos factores más importantes son el coste computacional y el salt. Cuanto más cueste aplicar un algoritmo hash, más costará analizar su salida por fuerza bruta.
PHP incluye dos funciones que pueden aplicar hash usando el algoritmo que se le especifique.
La primera función hash es crypt(), que de forma nativa soporta varios algoritmos hash. Al usar esta función, tendremos garantías de que el algoritmo elegido estará disponible, ya que PHP trae una implementación nativa de cada uno de los algoritmos soportados, en caso de que alguna de estas funciones no estén incluídas en el sistema.
La segunda función es hash(), que soporta muchos más algoritmos y variantes que crypt(), pero no soporta a alguno de los algoritmos que crypt() sí. La extensión hash está incluída en PHP, puede se puedes deshabilitar en tiempo de compilación, por lo que no se garantiza su disponibilidad, mientras que la de crypt() sí, ya que forma parte del nucleo de PHP.
El algoritmo recompendad para usar al hacer hash en contraseñas es Blowfish, ya que es significativamente más caro computacionalmente que MD5 o SHA1, a la vez que es escalable.
Un salt criptográfico es un dato que se utiliza durante el proceso de hash para eliminar la posibilidad de que el resultado pueda buscarse a partir de una lista de pares precalculados de hash y sus entradas originales, conocidas como tablas rainbow.
Es decir, un salt es un pequeño dato añadido que hace que los hash sean significantemente más difíciles de crackear. Existe un gran número de servicios online que ofrecen grandes listas de códigos hash precalculados, junto con sus datos de entrada originales. El uso de salt hace muy difícil o imposible encontrar el hash resultante en cualquiera de estas listas.