Qual è il modo giusto per implementare l'hashing delle password con chiave?

1

Come menzionato in questo meraviglioso link , il modo per ottenere un hash PBKDF2 di una password data dall'utente fornita

  1. una password (ovviamente),
  2. a salt (generato generatore di numeri casuali crittografato sicuro.
  3. numero di iterazioni (scelto abbastanza alto da essere sicuro mentre si bilancia la tolleranza di usabilità dell'applicazione)
  4. Dimensione hash (lunghezza dell'hash da calcolare)

/** * 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(); } Ora la mia domanda è:

Come dovrebbe essere implementato l'hashing con chiave per la password?

Sulla base della mia lettura, questa è la mia linea di pensiero. Si prega di convalidare.

  • Mantieni l'argomento salt al metodo pbkdf2 (nello snippet di codice sopra) secret (procuralo da un HSM altamente sicuro anziché memorizzandolo in il database accanto all'hash della password quando necessario).

  • Poiché il sale deve essere casuale (per proteggerli dagli attacchi rainbow tables / dictionary), il sale fornito a pbkdf2 dovrebbe essere una concatenazione della chiave e un byte casuale generato da un CSPRNG.

    [salt] = [chiave segreta] + [byte casuali da un CSPRNG]

Infine, avrò il coraggio di fare una domanda stupida (oserei chiedere poiché il numero elevato di iterazioni sta ponendo un serio problema di usabilità dal momento che dobbiamo autenticarci per il 90% dei casi d'uso nella nostra applicazione)

Possiamo ridurre il conteggio delle iterazioni o fare a meno di esso poiché abbiamo aggiunto un ulteriore livello di sicurezza attraverso l'hashing con chiave?

P.S : sono consapevole del valore aggiunto dagli algoritmi di hashing lenti, riducendo la possibilità che le password vengano compromesse da attacchi a forza bruta. Voglio solo che gli esperti commentino l'aggiunta del valore di sicurezza tramite Keyed Hashing VS con un algoritmo Slow Hashing con sale non segreto.

    
posta acthota 27.11.2014 - 07:58
fonte

1 risposta

1

Un modo per combinare l'hash della password con una chiave segreta consiste nell'avere un dispositivo separato (ad esempio HSM) che crittografa gli hash delle password inviati dal server di autenticazione utilizzando una chiave conosciuta solo dal dispositivo stesso.

All'accesso dell'utente, il tuo server di autenticazione calcola un hash lento (ad esempio, bcrypt) con un'adeguata impostazione dei costi (qualsiasi cosa sia tollerabile per il server / situazione, 5ms, 20ms, 100ms?) e passa l'hash risultante al dispositivo di crittografia, che a sua volta restituisce il blob crittografato che è possibile verificare sul server di autenticazione (il server di autenticazione memorizza l'identificatore di hash, il costo, il sale, il possibile "codice identificativo della chiave del dispositivo di crittografia" e il blob crittografato).

Il "dispositivo di crittografia" non consente al server di autenticazione di decrittografare gli hash, solo crittografare e restituire il blob crittografato al server di autenticazione.

La chiave separata aggiunge un altro livello di sicurezza se non si trova nello stesso modello di thread del database auth server / hash.

Usando un dispositivo di accesso separato, che contiene una strong chiave, sconfigge gli attacchi che si impadroniscono del database degli utenti trapelati (e dei file auth server).

    
risposta data 27.11.2014 - 14:51
fonte

Leggi altre domande sui tag