ventajas tipos significado salazon salado sal que metodo los ejemplos desventajas conservan conservacion con chacinados alimentos security hash passwords salt password-hash

security - tipos - Mejores prácticas: contraseñas de salazón y ají?



salazon ventajas y desventajas (4)

Encontré una discusión en la que aprendí que lo que había estado haciendo no era saltear las contraseñas, sino salpicarlas, y desde entonces comencé a hacer ambas cosas con una función como:

hash_function($salt.hash_function($pepper.$password)) [multiple iterations]

Ignorando el algoritmo hash elegido (quiero que sea una discusión sobre sales y pimientos y no sobre algoritmos específicos pero estoy usando uno seguro), ¿es esta una opción segura o debería estar haciendo algo diferente? Para aquellos que no están familiarizados con los términos:

  • Una sal es un valor generado aleatoriamente almacenado con la cadena en la base de datos diseñada para imposibilitar el uso de tablas hash para descifrar las contraseñas. Como cada contraseña tiene su propia sal, todas deben ser forzadas en bruto individualmente para romperlas; sin embargo, como la sal se almacena en la base de datos con el hash de la contraseña, un compromiso de la base de datos significa perder ambos.

  • Un pimiento es un valor estático de todo el sitio almacenado por separado de la base de datos (por lo general, codificado en el código fuente de la aplicación) que está destinado a ser secreto. Se usa para que un compromiso de la base de datos no cause que toda la tabla de contraseñas sea brutalmente ejecutable.

¿Hay algo que me falta y está salando y acribillar mis contraseñas la mejor opción para proteger la seguridad de mi usuario? ¿Hay algún defecto de seguridad potencial para hacerlo de esta manera?

Nota: suponga, a los fines de la discusión, que la aplicación y la base de datos están almacenadas en máquinas separadas, no comparten contraseñas, etc. por lo que una violación del servidor de la base de datos no significa automáticamente una violación del servidor de la aplicación.


De acuerdo. Dado que tengo que escribir sobre esto over y over , haré una última respuesta canónica solo con pimienta.

El aparente al revés de los pimientos

Parece bastante obvio que los pimientos deberían hacer que las funciones hash sean más seguras. Quiero decir, si el atacante solo obtiene su base de datos, entonces la contraseña de los usuarios debería ser segura, ¿no? Parece lógico, ¿verdad?

Es por eso que muchas personas creen que los pimientos son una buena idea. Que tiene sentido".

La realidad de los pimientos

En los ámbitos de seguridad y criptografía, "tener sentido" no es suficiente. Algo tiene que ser comprobable y tener sentido para que se considere seguro. Además, tiene que ser implementable de una manera sostenible. El sistema más seguro que no se puede mantener se considera inseguro (porque si se rompe alguna parte de esa seguridad, todo el sistema se desmorona).

Y los pimientos no se ajustan ni a los modelos comprobables ni a los que se pueden mantener ...

Problemas teóricos con pimientos

Ahora que hemos preparado el escenario, veamos qué pasa con los pimientos.

  • Alimentar con un hash a otro puede ser peligroso.

    En su ejemplo, usted hace hash_function($salt . hash_function($pepper . $password)) .

    Sabemos por experiencia que "solo alimentar" un resultado de hash en otra función hash puede disminuir la seguridad general. La razón es que ambas funciones hash pueden convertirse en un objetivo de ataque.

    Es por eso que los algoritmos como PBKDF2 usan operaciones especiales para combinarlos (hmac en ese caso).

    El punto es que, si bien no es gran cosa, tampoco es algo trivial lanzarlo. Los sistemas criptográficos están diseñados para evitar casos de "debería funcionar", y en su lugar se centran en casos "diseñados para funcionar".

    Si bien esto puede parecer puramente teórico, de hecho no lo es. Por ejemplo, Bcrypt no puede aceptar contraseñas arbitrarias . Así que pasar bcrypt(hash(pw), salt) puede resultar en un hash mucho más débil que bcrypt(pw, salt) si hash() devuelve una cadena binaria.

  • Trabajando contra diseño

    La forma en que bcrypt (y otros algoritmos hash de contraseñas) fueron diseñados es para trabajar con una sal. El concepto de pimienta nunca fue introducido. Esto puede parecer una trivialidad, pero no lo es. La razón es que una sal no es un secreto. Es solo un valor que puede ser conocido por un atacante. Por otro lado, un pimiento, por definición, es un secreto criptográfico.

    Los algoritmos hash de contraseñas actuales (bcrypt, pbkdf2, etc.) están diseñados para tomar solo un valor secreto (la contraseña). Agregar otro secreto en el algoritmo no se ha estudiado en absoluto.

    Eso no quiere decir que no es seguro. Significa que no sabemos si es seguro. Y la recomendación general con seguridad y criptografía es que, si no lo sabemos, no lo es.

    Entonces, hasta que los algoritmos sean diseñados y examinados por criptógrafos para su uso con valores secretos (pimientos), los algoritmos actuales no deberían usarse con ellos.

  • La complejidad es el enemigo de la seguridad

    Créalo o no, la complejidad es el enemigo de la seguridad . Hacer un algoritmo que se vea complejo puede ser seguro o no lo es. Pero las posibilidades son bastante significativas de que no es seguro.

Problemas significativos con los pimientos

  • No es sostenible

    Su implementación de pimientos impide la capacidad de rotar la tecla de pimienta. Como el pimiento se usa en la entrada de la función de una sola vía, nunca puede cambiar la pimienta durante el tiempo de vida del valor. Esto significa que tendrías que inventar algunos hacks no deseados para que sea compatible con la rotación de claves.

    Esto es extremadamente importante ya que se requiere siempre que almacene secretos criptográficos. No tener un mecanismo para rotar claves (periódicamente, y después de una violación) es una gran vulnerabilidad de seguridad.

    Y su enfoque actual de pimienta requeriría que cada usuario tenga su contraseña completamente invalidada por una rotación, o espere hasta su próximo inicio de sesión para rotar (lo que puede ser nunca) ...

    Lo que básicamente hace que su enfoque sea un inmediato no-go.

  • Requiere que hagas rodar tu propio cripto

    Dado que ningún algoritmo actual admite el concepto de pimienta, es necesario componer algoritmos o inventar nuevos para apoyar un pimiento. Y si no puede ver inmediatamente por qué eso es realmente malo:

    Cualquiera, desde el aficionado más despistado hasta el mejor criptógrafo, puede crear un algoritmo que él mismo no puede descifrar.

    NUNCA ruede su propia criptografía ...

La mejor manera

Entonces, de todos los problemas detallados anteriormente, hay dos formas de manejar la situación.

  • Simplemente use los algoritmos tal como existen

    Si usa bcrypt o scrypt correctamente (con un alto costo), todas las contraseñas menos los diccionarios más débiles deberían ser estadísticamente seguros. El récord actual para hash bcrypt al costo 5 es 71k hashes por segundo. A ese ritmo, incluso una contraseña aleatoria de 6 caracteres tardaría años en descifrar. Y teniendo en cuenta que mi costo mínimo recomendado es 10, eso reduce los hash por segundo en un factor de 32. Entonces estaríamos hablando de solo 2200 hashes por segundo. A ese ritmo, incluso algunas frases de diccionario o modificaciones pueden ser seguras.

    Además, deberíamos verificar esas clases débiles de contraseñas en la puerta y no permitirlas. A medida que el descifrado de contraseñas se hace más avanzado, también lo deberían hacer los requisitos de calidad de las contraseñas. Sigue siendo un juego estadístico, pero con una técnica de almacenamiento adecuada y contraseñas seguras, todo el mundo debería estar prácticamente seguro ...

  • Encriptar el hash de salida antes del almacenamiento

    Existe en el ámbito de la seguridad un algoritmo diseñado para manejar todo lo que hemos dicho anteriormente. Es un cifrado de bloque. Es bueno, porque es reversible, por lo que podemos rotar las teclas (¡ay! ¡Mantenibilidad!). Es bueno porque se está usando según lo diseñado. Es bueno porque no le da al usuario ninguna información.

    Veamos esa línea de nuevo. Digamos que un atacante conoce su algoritmo (que es necesario para la seguridad, de lo contrario es la seguridad a través de la oscuridad). Con un enfoque de pimiento tradicional, el atacante puede crear una contraseña de centinela, y como conoce la sal y la salida, puede forzar la fuerza bruta de la pimienta. Ok, eso es una posibilidad remota, pero es posible. Con un cifrado, el atacante no obtiene nada. Y dado que la sal se asigna al azar, una contraseña de vigilancia ni siquiera lo ayudará. Entonces, lo mejor que les queda es atacar la forma encriptada. Lo que significa que primero tienen que atacar su hash cifrado para recuperar la clave de cifrado y luego atacar los hash. Pero hay mucha investigación sobre el ataque de cifras, por lo que queremos confiar en eso.

TL / DR

No use pimientos. Hay una gran cantidad de problemas con ellos, y hay dos formas mejores: no usar ningún secreto del lado del servidor (sí, está bien) y cifrar el hash de salida usando un cifrado de bloques antes del almacenamiento.


El punto de sal y pimienta es aumentar el costo de una búsqueda de contraseña pre calculada, llamada tabla de arcoíris.

En general, es difícil encontrar una colisión para un solo hash (suponiendo que el hash es seguro). Sin embargo, con hash cortos, es posible usar la computadora para generar todos los hash posibles en una búsqueda en un disco duro. Esto se llama una tabla del arco iris. Si crea una tabla arcoiris, puede salir al mundo y encontrar rápidamente contraseñas plausibles para cualquier hash (sin sal).

El objetivo de un pimiento es hacer que la tabla arcoíris necesaria para hackear su lista de contraseñas sea única. Perdiendo así más tiempo al atacante para construir la tabla del arco iris.

Sin embargo, el objetivo de la sal es hacer que la tabla del arcoíris para cada usuario sea única para el usuario, aumentando aún más la complejidad del ataque.

Realmente, el objetivo de la seguridad informática casi nunca es hacer que (matemáticamente) sea imposible, solo matemáticamente y físicamente impráctico (por ejemplo, en sistemas seguros, se necesitaría toda la entropía del universo (y más) para calcular la contraseña de un solo usuario).


No veo que almacenar un valor codificado en el código fuente tenga relevancia de seguridad. Es seguridad a través de la oscuridad.

Si un hacker adquiere su base de datos, podrá comenzar a usar fuerza bruta en sus contraseñas de usuario. No le tomará mucho tiempo al hacker identificar su pimienta si logra descifrar algunas contraseñas.


Primero deberíamos hablar sobre la ventaja exacta de un pimiento :

  • El pimiento puede proteger las contraseñas débiles de un ataque de diccionario, en el caso especial, donde el atacante tiene acceso de lectura a la base de datos (que contiene los hash) pero no tiene acceso al código fuente con el pimiento.

Un escenario típico sería inyección de SQL, copias de seguridad descartadas, servidores descartados ... Estas situaciones no son tan poco comunes como suena, y a menudo no están bajo su control (alojamiento de servidor). Si utiliza...

  • Una sal única por contraseña
  • Un algoritmo hash lento como BCrypt

... las contraseñas seguras están bien protegidas. Es casi imposible forzar una contraseña segura en esas condiciones, incluso cuando se conoce la sal. El problema son las contraseñas débiles, que son parte de un diccionario de fuerza bruta o son derivaciones de ellas. Un ataque de diccionario revelará esos muy rápido, porque solo prueba las contraseñas más comunes.

La segunda pregunta es cómo aplicar el pimiento ?

Una manera a menudo recomendada de aplicar un pimiento, es combinar la contraseña y el pimiento antes de pasarlo a la función hash:

$pepperedPassword = hash_hmac(''sha512'', $password, $pepper); $passwordHash = bcrypt($pepperedPassword);

Sin embargo, hay otra manera aún mejor:

$passwordHash = bcrypt($password); $encryptedHash = encrypt($passwordHash, $serverSideKey);

Esto no solo permite agregar un secreto del lado del servidor, sino que también permite intercambiar $ serverSideKey, en caso de ser necesario. Este método implica un poco más de trabajo, pero si el código existe una vez (biblioteca) no hay ninguna razón para no usarlo.