In alcune circostanze, i peperoni possono essere utili.
Come esempio tipico, diciamo stai creando un'applicazione web. Si compone di codice webapp (in esecuzione in alcuni framework webapp, ASP.NET MVC, Pyramid su Python, non importa ) e un database SQL per l'archiviazione. La webapp e il DB SQL vengono eseguiti su server fisici diversi .
L'attacco più comune contro il database è un attacco SQL Injection di successo. Questo tipo di attacco non ha necessariamente accesso al tuo codice webapp, perché la webapp funziona su un server diverso e amp; user-ID.
Devi memorizzare le password in modo sicuro nel database e trovare qualcosa sotto forma di:
$hashed_password = hash( $salt . $password )
dove $salt
è memorizzato in testo normale nel database, insieme alla rappresentazione $hashed_password
e scelti casualmente per ogni password nuova o modificata .
Il aspetto più importante di ogni schema di hashing delle password è che hash
è una funzione hash crittografata slow , vedi link per ulteriori informazioni di base.
La domanda è quindi, dato che è quasi zero l'impegno di aggiungere un valore costante al codice dell'applicazione e che il codice dell'applicazione non tipicamente verrà compromesso durante un SQL Injection Attack, il seguente è sostanzialmente migliore del precedente?
$hashed_password = hash( $pepper . $salt . $password )
dove $salt
è memorizzato in testo normale nel database e $pepper
è una costante memorizzata in testo normale nel codice dell'applicazione (o configurazione se il codice è utilizzato su più server o l'origine è pubblica).
Aggiungere questo $pepper
è facile - stai solo creando una costante nel tuo codice, inserendo un grande valore casuale crittograficamente sicuro (per esempio 32byte da / dev / urandom hex o base64 encoded) in esso, e usando quello costante nella funzione di hashing della password. Se si dispone di utenti esistenti è necessaria una strategia di migrazione, ad esempio rehash della password al successivo accesso e memorizzare un numero di versione della strategia di hashing della password accanto all'hash.
Risposta:
L'utilizzo di $pepper
fa aggiunge alla forza della password hash se compromissione del database non implica compromissione dell'applicazione . Senza la conoscenza del pepe, le password rimangono completamente sicure. A causa della specifica password salt non riesci nemmeno a scoprire se due password nel database sono uguali o meno.
Il motivo è che hash($pepper . $salt . $password)
crea effettivamente una funzione pseudo casuale con $pepper
come chiave e $salt.$password
come input (per% sesi con% di candidati come PBKDF2 con SHA *, bcrypt o scrypt). Due delle garanzie di una funzione pseudo casuale sono che non è possibile dedurre l'input dall'output sotto una chiave segreta e né l'output dall'input senza la conoscenza della chiave. Sembra molto simile alla proprietà unidirezionale delle funzioni hash, ma la differenza sta nel fatto che con valori di entropia bassi come le password è possibile enumerare efficacemente tutti i valori possibili e calcolare le immagini sotto la funzione di hash pubblico e quindi trovare il valore di cui l'immagine corrisponde alla pre-immagine. Con una funzione pseudo casuale non puoi farlo senza la chiave (cioè senza il pepe) dato che non puoi nemmeno calcolare l'immagine di un singolo valore senza la chiave.
Il ruolo importante di hash
in questa impostazione entra in gioco se si ha accesso al database per un tempo prolungato e si può ancora lavorare normalmente con l'applicazione dall'esterno. Senza $salt
puoi impostare la password di un account che controlli con un valore noto $salt
e confrontare l'hash con la password di una password sconosciuta $passwordKnown
. Come $passwordSecret
se e solo se hash($pepper . $passwordKnown)==hash($pepper . $passwordSecret)
è possibile confrontare una password sconosciuta rispetto a qualsiasi valore scelto (come tecnicità presumo resistenza alla collisione della funzione hash). Ma con il sale si ottiene $passwordKnown==$passwordSecret
se e solo se hash($pepper . $salt1 . $passwordKnown)==hash($pepper . $salt2 . $passwordSecret)
e come $salt1 . $passwordKnown == $salt2 . $passwordSecret
e $salt1
sono stati scelti casualmente per $salt2
e rispettivamente $passwordKnown
i sali non saranno mai uguali (assumendo valori random sufficientemente ampi come 256 bit) e quindi non è più possibile confrontare le password l'una con l'altra.