In alcune circostanze, i peperoni possono essere utili.
Come esempio tipico, supponiamo che tu stia creando un'applicazione web. Consiste di codice webapp (in esecuzione in alcuni framework webapp, ASP.NET MVC, Pyramid on Python, non importa) e un database SQL per l'archiviazione. La webapp e il database SQL vengono eseguiti su server fisici diversi .
L'attacco più comune contro il database è un attacco SQL Injection riuscito. Questo tipo di attacco non ottiene necessariamente l'accesso al codice della tua webapp, perché la webapp viene eseguita su un altro server ID utente &.
Devi memorizzare le password in modo sicuro nel database e trova qualcosa sotto forma di:
$ hashed_password = hash ($ salt. $ password)
dove $ salt
è memorizzato come testo normale nel database, insieme alla rappresentazione $ hashed_password
e scelto a caso per ogni password nuova o modificata .
Il l'aspetto più importante di ogni schema di hashing delle password è che hash
è una funzione hash crittograficamente sicura lenta , vedi https: //security.stackexchange .com / a / 31846/10727 per una maggiore conoscenza di base.
La domanda è quindi, dato che è quasi nullo aggiungere un valore costante al codice dell'applicazione e che il codice dell'applicazione non sarà in genere compromesso dur durante un attacco SQL Injection, quanto segue è quindi sostanzialmente migliore di quanto sopra?
$ hashed_password = hash ($ pepper. $ sale. $ 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 viene 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 (ad esempio 32 byte da / dev / urandom hex o base64 codificato) in esso e utilizzando quella costante nella funzione di hashing della password. Se hai utenti esistenti, hai bisogno di una strategia di migrazione, ad esempio modifica la password all'accesso successivo e memorizza un numero di versione della strategia di hashing della password insieme all'hash.
Risposta:
L'uso di $ pepper
non aggiunge alla forza dell'hash della password se la compromissione del database non implica la compromissione dell'applicazione. Senza la conoscenza del pepe le password rimangono completamente sicure. A causa del salt specifico per la password non puoi nemmeno scoprire se due password nel database sono uguali o meno.
Il motivo è che hash ($ pepper. $ Salt. $ Password)
crea efficacemente una funzione pseudo casuale con $ pepper
come chiave e $ salt. $ password
come input (per candidati hash
sani 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 nemmeno l'output dall'input senza la conoscenza della chiave. Questo suona molto come la proprietà unidirezionale delle funzioni hash, ma la differenza sta nel fatto che con valori di entropia bassi come le password puoi enumerare efficacemente tutti i valori possibili e calcolare le immagini sotto la funzione hash pubblica e quindi trovare il valore il cui l'immagine corrisponde alla pre-immagine. Con una funzione pseudo casuale non puoi farlo senza la chiave (cioè senza il pepe) in quanto non puoi nemmeno calcolare l'immagine di un singolo valore senza la chiave.
L'importante ruolo di $ salt
in questa impostazione entra in gioco se hai accesso al database per un periodo di tempo prolungato e puoi ancora lavorare normalmente con l'applicazione dall'esterno. Senza $ salt
potresti impostare la password di un account che controlli su un valore noto $ passwordKnown
e confrontare l'hash con la password di una password sconosciuta $ passwordSecret
. Come hash ($ pepper. $ PasswordKnown) == hash ($ pepper. $ PasswordSecret)
se e solo se $ passwordKnown == $ passwordSecret
puoi confrontare una password sconosciuta con qualsiasi valore scelto (come tecnicismo presumo la resistenza alle collisioni della funzione hash). Ma con il salt si ottiene hash ($ pepper. $ Salt1. $ PasswordKnown) == hash ($ pepper. $ Salt2. $ PasswordSecret)
se e solo se $ salt1. $ passwordKnown == $ salt2. $ passwordSecret
e come $ salt1
e $ salt2
sono stati scelti casualmente per $ passwordKnown
e rispettivamente $ passwordSecret
i sali non saranno mai gli stessi (assumendo valori casuali abbastanza grandi come 256 bit) e non potrai più confrontare le password tra loro.