¿Cuál es la forma correcta de implementar el hash con contraseña?

1

Como se menciona en este maravilloso enlace , la forma de obtener un hash PBKDF2 de una contraseña dada por el usuario

  1. una contraseña (por supuesto),
  2. a salt (Generador de números aleatorios de seguridad criptográficamente generado).
  3. recuento de iteraciones (elegido lo suficientemente alto como para ser seguro mientras se equilibra la tolerancia de uso de la aplicación)
  4. Tamaño de hash (longitud del hash a calcular)

/** * Computes the PBKDF2 hash of a password. * * @param password the password to hash. * @param salt the salt * @param iterations the iteration count (slowness factor) * @param bytes the length of the hash to compute in bytes * @return the PBDKF2 hash of the password */ private static byte[] pbkdf2(char[] password, byte[] salt, int iterations, int bytes) throws NoSuchAlgorithmException, InvalidKeySpecException { PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, bytes * 8); SecretKeyFactory skf = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM); return skf.generateSecret(spec).getEncoded(); } Ahora mi pregunta es:

¿Cómo se debe implementar el hash con clave para la contraseña?

Según mi lectura, esta es mi línea de pensamiento. Por favor valide.

  • Mantenga el argumento salt para el método pbkdf2 (en el fragmento de código anterior) en secreto (obténgalo de un HSM altamente seguro en lugar de almacenándolo en la base de datos junto con el hash de contraseña cuando sea necesario).

  • Dado que la sal debe ser aleatoria (para protegerlos de las tablas de arco iris / ataques de diccionario), la sal proporcionada al pbkdf2 debe ser una concatenación de la clave y un byte aleatorio generado desde un CSPRNG.

    [sal] = [clave secreta] + [bytes aleatorios de un CSPRNG]

Finalmente, me atreveré a hacer una pregunta tonta (me atreveré a hacerla, ya que el alto número de iteraciones está planteando un problema serio de usabilidad ya que necesitamos autenticar el 90% de los casos de uso en nuestra aplicación)

¿Podemos reducir la cantidad de iteraciones O prescindir de ella ya que hemos agregado una capa adicional de seguridad a través del hash con clave?

P.S : soy consciente del valor que agregan los algoritmos de hash lento al reducir la posibilidad de que las contraseñas se vean comprometidas por los ataques de fuerza bruta. Solo quiero que los expertos comenten sobre el valor agregado de seguridad a través de Keyed Hashing VS que tiene un algoritmo de Slow Hashing con sal no secreta.

    
pregunta acthota 27.11.2014 - 07:58
fuente

1 respuesta

1

Una forma de combinar el hash de contraseña con una clave secreta es tener un dispositivo separado (es decir, HSM) que encripta los hashes de contraseña enviados desde el servidor de autenticación usando una clave que solo conoce el propio dispositivo.

En el inicio de sesión del usuario, su servidor de autenticación calcula un hash lento (por ejemplo, bcrypt) con la configuración de costo adecuada (lo que sea tolerable para el servidor / situación, 5ms, 20ms, 100ms?) y pasa el hash resultante al dispositivo de cifrado. que a su vez devuelve el blob encriptado que puede verificar en el servidor de autenticación (el servidor de auth almacena el identificador de hash, el costo, la sal, el posible "material de identificador de clave de dispositivo de encriptado" y el blob encriptado).

El "dispositivo de encriptación" no permitirá que el servidor de autenticación descifre los hashes, solo encripta y devuelve el blob encriptado al servidor de autenticación.

La clave separada agrega otra capa de seguridad si no está en el mismo modelo de subproceso que la base de datos del servidor de autenticación / hash.

El uso de un dispositivo de acceso angosto e independiente que contiene una clave fuerte elimina los ataques que se apoderan de la base de datos de usuarios filtrados (y de los archivos del servidor de autenticación).

    
respondido por el timoh 27.11.2014 - 14:51
fuente

Lea otras preguntas en las etiquetas