La prima volta che un utente accede alla nostra app, ricaviamo una chiave AES dalla sua password usando PBKDF2. Il tasto AES viene tenuto solo nella RAM e utilizzato per crittografare e avvolgere altre chiavi e dati durante la sessione.
Quando termina la sessione corrente, gettiamo via la chiave ma conserviamo i dati crittografati e le impostazioni di derivazione (conteggio salt / iteration / etc.) per la prossima volta.
Nei login successivi, ri-deriviamo la chiave in base alla password e alle impostazioni, ma vogliamo verificare che la chiave (password) sia valida (con un ragionevole livello di sicurezza) prima di tentare di usarla.
Non vogliamo anche calcolare un hash sulla password perché la derivazione della chiave è già (volutamente) long-running e non vogliamo rendere quel processo più lungo con un altro algoritmo hash di lunga durata.
Ho visto alcune soluzioni a questo, ma mi chiedo se ci sia uno standard da seguire. Quello che ho visto finora:
- In Cryptography Engineering, Schneier e altri suggeriscono di prendere i dati hash dall'iterazione n-1 della funzione di derivazione e di eseguire l'hashing con sale, password, ecc. per formare un codice di verifica. È possibile memorizzare questo e calcolare lo stesso codice per il candidato mentre si ottiene la chiave. Se non corrispondono, tu rifiuti. Lato negativo: se utilizzi le librerie crittografiche di terze parti, probabilmente non sarà possibile accedere allo stato interno di PBKDF2 per farlo.
- Calcola qualcosa come
SHA256(key+salt+password)
e memorizzalo. Calcola per il candidato e rifiuta se non corrispondono. -
Usa la chiave per crittografare qualcosa con un pattern o suffisso noto e memorizzala. per es.
E(key, <32 bytes random data> + <32 bytes of 0>'.
Archivia questo, decrittalo usando la chiave candidata e controlla se il suffisso corrisponde. Il numero di 0 che scegli determina la possibilità di un falso positivo.
Quest'ultima sembra semplice ed efficace, ma sto cercando consigli chiari da un esperto / autorità in materia.