el límite de 72 caracteres de BCrypt y usarlo como un algoritmo de resumen general

13

Objetivo: tener autenticación basada en token / cookie que no requiera mantener sesiones en el servidor

TL; DR: ¿Cuál es, si existe, el mecanismo aceptado para solucionar la limitación de 72 caracteres de BCrypt?

Versión larga:

Después de leer esta respuesta intenté implementar la autenticación en un servidor basado en REST utilizando BCrypt como un algoritmo hash y un secreto del lado del servidor de rotación. La idea básica era que, tras la autenticación exitosa con un nombre de usuario y contraseña, el servidor configuraría una cookie que contenía un hash basándose en la concatenación de lo siguiente:

  • El secreto del lado del servidor
  • El ID de usuario y los grupos a los que pertenece el usuario
  • La hora en que se entregó el token

Esto se incluiría con un salt y el resultado iría a la cookie, para que el servidor la lea y verifique (es posible porque la identificación del usuario, los grupos y la fecha son transmitidos en forma simple por el cliente, y el secreto del lado del servidor está en la memoria, y el secreto sirve como garantía de que el cliente no hizo todos los demás valores por sí mismos).

Todo esto funcionó bien hasta que me di cuenta de que BCrypt tiene un límite de 72 caracteres en el texto sin cifrar que está encriptado (cualquier cosa después de esos 72 caracteres no influye en el hash de salida).

Esto es un problema porque los datos anteriores suman más de 72 caracteres y permiten que el tiempo, la identificación del usuario, los grupos o la clave secreta sean 'los últimos' en la entrada y no influyan en los agujeros abiertos de salida en la seguridad del sistema. (o los tokens antiguos son infinitamente válidos, o las personas pueden modificar su ID de usuario / rol de manera arbitraria).

Irónicamente, cuando finalmente descubrí por qué mi sistema producía hashes idénticos basados en diferentes entradas y buscaba en Google, parece que este tipo de situación fue previsto por algunos .

De todos modos, la pregunta: ¿Cuál, si existe, es el mecanismo aceptado para evitar la limitación de 72 caracteres de BCrypt?

Algunos pensamientos preventivos: inventarme sus propias variaciones en algoritmos criptográficos estándar es algo que me advirtieron durante el tiempo que puedo recordar, por lo que no estoy 100% seguro de cuál sería el mejor curso de acción.

Las opciones obvias incluyen:

  • dividiendo la entrada y aplicando BCrypt a cada uno de ellos y / o en cascada;
  • usando otro hash (¿no criptográfico?) en la entrada para reducir su tamaño
  • usar compresión simple (pero eso podría no ser efectivo con tan poco texto sin formato)
  • cambiar a otro algoritmo (SHA-3 se finalizó recientemente, por ejemplo).

(puede haber otras cosas incorrectas con la idea anterior, en cuyo caso, por supuesto, me encantaría que me corrigieran)

    
pregunta Gijs 12.10.2012 - 18:30
fuente

3 respuestas

16

El mecanismo aceptado es "no lo hagas".

¿Para qué sirve bcrypt? Es bueno en ser lento . ¿Por qué querría que una función criptográfica, o simplemente cualquier función, fuera lenta? Esto tiene sentido solo cuando la entrada a la función es un secreto de baja entropía , lo que significa "algún valor que el adversario podría concebir, y de manera realista, explorar exhaustivamente". Las contraseñas son secretos de baja entropía: es bien sabido que cuando los seres humanos pueden elegir cadenas secretas en la privacidad de su cerebro, la mayoría seleccionará contraseñas "ingeniosas" que son absolutamente débiles contra ataques de diccionario . La única defensa restante es imponer el uso de un proceso de hashing inherentemente lento, que es equivalente a enviar todas las computadoras involucradas (y, en particular, las computadoras del atacante) a principios de los 80, cuando 1 MHz era una frecuencia de CPU muy alta.

En su caso, el "valor secreto" es el secreto de servidor ; no debe ser de baja entropía (el servidor es una máquina, no un ser humano; puede recordar claves largas). Si el secreto del servidor es un valor de baja entropía, entonces lo está haciendo mal.

Por lo tanto, no hay necesidad de bcrypt o cualquier otra función deliberadamente retardada aquí. Lo que realmente desea es un Código de autenticación de mensaje : desea almacenar algunos valores en el lado del cliente (como una cookie), pero también desea verificar que no se realicen devoluciones de valores falsificados; Este es un asunto de integridad , y un MAC es la herramienta correcta para eso. Use HMAC / SHA-256, con el "secreto del servidor" como clave MAC (su hashing hecho en casa de varios valores, incluido el secreto del servidor, es solo un MAC casero disfrazado, por lo que puede hacerlo correctamente reutilizando el estándar, Solución robusta, experta vetada, y eso es HMAC).

Por supuesto, una vez que comenzamos a usar el almacenamiento del lado del cliente, se vuelve tentador almacenar valores que el propio cliente no debería aprender. Para el requisito de integridad , agregamos confidencialidad . Para eso, necesitamos encriptación. Hacer el cifrado correctamente es difícil, y combinar el cifrado y un MAC aún más. En ese caso, hazte un favor: utiliza el modo cifrado autenticado , que lo hará correctamente con el mínimo de molestia (te recomiendo EAX ).

Al sugerir a Keccak (SHA-3), usted demuestra que padece una enfermedad muy común, que se puede llamar el "síndrome del iPhone": anhela el nuevo dispositivo. Para. Cuando se trata de la seguridad en general y la criptografía en particular, esto solo llevará a un sufrimiento masivo. En la criptografía, "nuevo" es otro nombre para "malo".

El mejor tipo de algoritmos criptográficos es algoritmos antiguos que aún están vivos . No hay mejor criterio para la seguridad. En ese sentido, SHA-2 es mejor que SHA-3, y seguirá siéndolo en el futuro, hasta que se encuentre un problema con estas funciones. La gente del NIST recomienda explícitamente SHA-2 y niega cualquier sugerencia de que SHA-3 sea mejor que SHA-2.

    
respondido por el Thomas Pornin 12.10.2012 - 19:51
fuente
2

Podrías usar otra función de derivación de claves como scrypt o pbkdf2 + sha2 (o sha3).

Aunque creo que este enfoque de autenticación es un desperdicio de ancho de banda, memoria y CPU, y para terminar es menos seguro. Para que el estiramiento de las teclas sea efectivo, debe ser pesado y deberá realizar este cálculo para cada solicitud. Creo que es mejor emitir una fuente criptográfica y respaldar el estado del servidor con una base de datos no relacional rápida como memcachd. Seguro que no es "RESTful", pero es un diseño más eficiente y más seguro.

Los mejores criptógrafos utilizan la criptografía cuando no hay otra opción. Plan en caso de fracaso.

    
respondido por el rook 12.10.2012 - 18:41
fuente
0

Parece que está intentando mantener el estado de la sesión sin el método habitual de almacenar los datos de la sesión en el extremo del servidor.

Aquí hay un mejor libro de cocina:

  1. Autentique el nombre de usuario y la contraseña (aquí puede usar bcrypt para validar la contraseña)
  2. Coloque toda la información de la sesión que desea almacenar en un blob serializado
  3. Cifre el blob con una clave de servidor fuerte y secreta, usando cifrado autenticado
  4. Envíe el blob en una cookie / campo de formulario oculto / ... (codificado en base64)

En la siguiente llamada:

  1. Descifrar / verificar el blob
  2. Anular los datos de la sesión
  3. Beneficio!

Todos estos pasos han sido probados en batalla.

    
respondido por el Jan Hertsens 21.09.2015 - 01:13
fuente

Lea otras preguntas en las etiquetas