¿Existe una mejor manera de aprovechar los algoritmos actuales 'aprobados', 'probados' y de memoria / CPU-costosos al usar sales y pimientos?

3

He leído sobre los conceptos presentados en estas dos preguntas:

La contraseña de pre-hash antes aplicando bcrypt para evitar restringir la longitud de la contraseña

¿Tendría sentido usar Bcrypt? y PBKDF2 juntos?

Creo que he encontrado una implementación que combina los conceptos presentados en ambas preguntas, mientras que posiblemente proporcione varias capas de seguridad.

Preguntas

  1. ¿Es esta implementación relativamente segura en comparación con la mayoría de los demás?
  2. ¿Me disparé en el pie encadenando múltiples funciones de esta manera?
  3. ¿Existe una mejor manera de aprovechar los algoritmos actuales 'aprobados', 'probados' y caros en memoria?
  4. ¿Cómo puedo mejorar esta implementación?
  5. ¿Hay un punto en el que los valores de sal y pimienta son lo suficientemente grandes como para dificultar el agrietamiento de los hashes al requerir más memoria y / o procesamiento?

Preocupaciones

  1. El hombre en el medio ataca
    • SSLStrip
    • falsificación ARP, secuestro de DNS y que actúa como proxy HTTP
      • Terminando la conexión SSL en el lado del atacante y enviando tráfico HTTP al usuario
  2. La contraseña de texto sin formato se maneja con el código del servidor
  3. Mesas arcoiris y problema de cumpleaños
  4. Algoritmos no probados
  5. Cálculo rápido y eficiente de hashes
  6. Credenciales realmente largas
  7. Falta de entropía adecuada
  8. El volcado de la base de datos de autenticación da como resultado la divulgación de sales y pimientos
  9. Almacenamiento de texto sin formato de correo electrónico

Soluciones

  1. Nunca envíe una contraseña de texto simple por el cable, y utilice SSL solo en el sitio
  2. Saltea y hash la contraseña antes de enviarla al servidor
  3. Los pimientos únicos del usuario se aplican en el servidor
  4. La cadena de hash termina con PBKDF2, un algoritmo revisado por RSA
  5. La cadena de hash utiliza bcrypt, ya que requiere 4kB de memoria
  6. Cualquier cadena de entrada a bcrypt se hash con SHA-512 para mantener el número de caracteres de entrada por debajo del máximo
  7. La sal y los pimientos serán cadenas largas y aleatorias
  8. Almacene sales privadas y pimientos en otro servicio al que solo se puede acceder desde la API interna
  9. Almacene los hashes de las direcciones de correo electrónico y las contraseñas en los servidores que manejan el tráfico público

Componentes

Algorithms

SHA-512, bcrypt, PBKDF2

Sales públicas

public_salt

Pimienta privada

email_pepper, bcrypt_pepper, pbkdf2_pepper

Usuario global

public_salt, email_pepper

Usuario único

bcrypt_pepper, pbkdf2_pepper

Proceso

  1. El usuario ingresa la dirección de correo electrónico y la contraseña en un formulario web y los envía para iniciar sesión.
  2. La dirección de correo electrónico y la cadena de la contraseña se procesan mediante PBKDF2 (por separado) con public_salt, y las dos claves de 1024 bits resultantes (email_key, password_key) se envían al servidor mediante SSL.
  3. El servidor vuelve a escribir email_key con PBKDF2 usando email_pepper con un mayor recuento de iteraciones para obtener el valor de storage_email_key.
  4. El servidor luego consulta un servicio solo interno para solicitar los pimientos únicos almacenados para el valor_clave_de_contenido almacenado, y recibe bcrypt_pepper y pbkdf2_pepper.
  5. la clave_clave_directa se utiliza mediante el uso de SHA-512 para reducir la longitud de la clave, por lo que bcrypt no trunca la entrada, lo que da como resultado un hash reducido.
  6. El hash reducido se hashizado utilizando bcrypt, con bcrypt_pepper, que da como resultado bcrypt_hash.
  7. bcrypt_hash luego se procesa usando PBKDF2 con pbkdf2_pepper, lo que resulta en el hash de contraseña final almacenado.

Descripción general

email_key = PBKDF2(email, public_salt)
password_key = PBKDF2(password, public_salt)
POST: keys -> SSL -> server
stored_email_key = PBKDF2(email_key, email_pepper)
server gets bcrypt_pepper, and pbkdf2_pepper
reduced_hash = SHA-512(password_key)
bcrypt_hash = bcrypt(reduced_hash, bcrypt_pepper)
pbkdf2_hash = PBKDF2(bcrypt_hash, pbkdf2_pepper)

Compuesto

Password - pbkdf2(bcrypt(sha512(pbkdf2(password, public_salt)), bcrypt_pepper), pbkdf2_pepper)
Email address - pbkdf2(pbkdf2(email_address, public_salt), email_pepper)

Con respecto al almacenamiento de direcciones de correo electrónico

  1. Las direcciones de correo electrónico solo son necesarias para notificaciones, restablecimientos de contraseñas y boletines.
  2. Las direcciones de correo electrónico se almacenarán como un hash PBKDF2 en cualquier sistema o clúster que maneje cualquier tráfico público.
  3. Las direcciones de correo electrónico se almacenarán encriptadas en un servicio accesible a través de una API disponible solo para el código interno que necesita enviar correos electrónicos a los destinatarios.

Me doy cuenta de que esto puede ser excesivo, pero realmente quiero asegurar que las contraseñas y las direcciones de correo electrónico se manejen y almacenen correctamente.

Específicos

Todavía estoy debatiendo sobre qué valores usar para el número de iteraciones en cada paso del proceso. Obviamente, voy a usar un número mayor de iteraciones en el servidor que en javascript.

Estoy pensando en generar claves de 1024 bits donde se usa PBKDF2, así como en usar sales de 2048 bits o mayores.

    
pregunta clay richardson 02.11.2012 - 02:29
fuente

1 respuesta

4

La primera regla de seguridad es: No enrolle su propio criptográfico .

Se le ocurrió un esquema complejo, que realmente no mejora nada en comparación con las mejores prácticas. Tampoco estoy seguro de que tenga claro qué es una sal ni un pimiento, y por qué se usa: una sal es un conjunto aleatorio de bytes de longitud fija y no se considera un secreto. Una pimienta es una clave (secreta).

Hash del lado del cliente
Los valores de hash en el lado del cliente no le ganan nada, porque:

  1. Ya estás usando SSL, por lo que todo está encriptado antes de enviarlo por cable
  2. Si hash, por ejemplo una contraseña, en el lado del cliente, el hash de la contraseña se convierte efectivamente en la contraseña.

Direcciones de correo electrónico
Por lo general, desea que la dirección de correo electrónico de los usuarios sea reversible / legible, ya que la necesitará en algún momento posterior para comunicarse con el usuario. Si solo tiene un valor derivado, no puede contactarlos.

Pre-hasheado contraseñas
BCrypt trunca cualquier contraseña a 55 bytes de entrada (excluyendo la sal ). 55 bytes pueden no parecer mucho a la luz de valores comúnmente citados de 128 bits, 256 bits o incluso 1024 bits. Sin embargo, las contraseñas comunes son realidad de longitudes en el rango de 6 a 10 caracteres.

Si quisiera permitir valores más largos, simplemente usaría

bcrypt(sha512($password)); *

La necesidad de un valor de pimienta se debate aquí . Si decide que desea almacenar sus contraseñas con pepper & sal, utilizar:

bcrypt(hash_hmac('sha256', $password, $pepper)); *

Según lo recomendado aquí .

*) En ambos ejemplos, supongo que usas una implementación de BCrypt que crea automáticamente un salt

    
respondido por el Jacco 02.11.2012 - 08:18
fuente

Lea otras preguntas en las etiquetas