Salt Generation e software open source

A quanto ho capito, la migliore pratica per la generazione di sali è quella di utilizzare alcune formule criptiche (o anche le costanti magiche) memorizzate nel codice sorgente.

Sto lavorando a un progetto che prevediamo di rilasciare come open source, ma il problema è che con la sorgente arriva la formula segreta per la generazione di sali, e quindi la possibilità di eseguire attacchi di rainbow table sul nostro sito.

Immagino che molte persone abbiano contemplato questo problema prima di me, e mi sto chiedendo quale sia la migliore pratica. Mi sembra che non abbia senso avere un sale del tutto se il codice è open source, perché i sali possono essere facilmente decodificati.

Pensieri?

In realtà, i sali devono essere unici per ogni voce. Anche se l’attaccante può calcolare il sale, rende estremamente difficile la creazione della tabella arcobaleno. Ciò è dovuto al fatto che il sale viene aggiunto alla password prima di essere sottoposto a hash, quindi aggiunge effettivamente al numero totale di voci che la tabella arcobaleno deve contenere per avere un elenco di tutti i possibili valori per un campo password.

Dal momento che le domande sulla salatura degli hash arrivano regolarmente e sembra esserci una certa confusione sull’argomento, ho esteso questa risposta.

Cos’è un sale?

Un salt è un insieme casuale di byte di una lunghezza fissa che viene aggiunto all’input di un algoritmo hash.

Perché è utile salare (o seminare) un hash?

L’aggiunta di un salt casuale a un hash assicura che la stessa password produca molti hash diversi. Il sale viene solitamente memorizzato nel database, insieme al risultato della funzione hash. La salatura di un hash è buona per una serie di motivi:

  1. La salatura aumenta notevolmente la difficoltà / il costo degli attacchi precomputi (incluse le tavole arcobaleno )
  2. Salting si assicura che la stessa password non risulti nello stesso hash. Questo assicura che non sia ansible determinare se due utenti hanno la stessa password. E, ancora più importante , non è ansible determinare se la stessa persona utilizza la stessa password su sistemi diversi.
  3. La salatura aumenta la complessità delle password, riducendo così notevolmente l’efficacia di entrambi gli attacchi Dizionario e Compleanno . (Questo è vero solo se il sale è immagazzinato separato dall’hash).
  4. La corretta salatura aumenta notevolmente la necessità di stoccaggio per gli attacchi di precomputazione, fino al punto in cui non sono più pratici. (8 caratteri alfanumerici sensibili al maiuscolo / minuscolo con 16 bit di sale, con hash a un valore di 128 bit, richiederebbero poco meno di 200 exabyte senza riduzione dell’arcobaleno).

Non c’è bisogno che il sale sia segreto.

Un sale non è una chiave segreta, invece un sale “funziona” rendendo la funzione hash specifica per ogni istanza. Con hash salato, non esiste una funzione hash, ma una per ogni valore di sale ansible. Questo impedisce all’attaccante di attaccare le password N hash per meno di N volte il costo dell’attacco di una password. Questo è il punto del sale.
Un “sale segreto” non è un sale, è chiamato “chiave”, e significa che non si sta più calcolando un hash, ma un Message Authentication Code (MAC). Il Computing MAC è un business complicato (molto più complicato del semplice schiacciare una chiave e un valore in una funzione hash) ed è un argomento completamente diverso.

Il sale deve essere casuale per ogni istanza in cui viene utilizzato. Questo assicura che un attaccante debba attaccare ogni hash salato separatamente.
Se fai affidamento sul fatto che il tuo sale (o algoritmo di salatura) è segreto, entri nei regni di Security Through Obscurity (non funzionerà). Molto probabilmente, non si ottiene ulteriore sicurezza dalla segretezza del sale; hai solo la calda sensazione di sicurezza. Quindi, invece di rendere il tuo sistema più sicuro, ti distrae dalla realtà.

Quindi, perché il sale deve essere casuale?

Tecnicamente, il sale dovrebbe essere unico . Il punto del sale deve essere distinto per ogni password con hash. Questo è inteso in tutto il mondo . Dato che non esiste un’organizzazione centrale che distribuisce sali unici su richiesta, dobbiamo fare affidamento sulla prossima cosa migliore, che è la selezione casuale con un generatore casuale imprevedibile, preferibilmente all’interno di uno spazio sale abbastanza grande da rendere improbabili le collisioni (due istanze che usano lo stesso valore sale).

Si è tentati di provare a ricavare un sale da alcuni dati che sono “presumibilmente unici”, come l’ID utente, ma tali schemi spesso falliscono a causa di alcuni dettagli sgradevoli:

  1. Se si utilizza ad esempio l’ID utente , alcuni malintenzionati, che attaccano sistemi distinti, possono semplicemente mettere in comune le proprie risorse e creare tabelle precompilate per gli ID utente da 1 a 50. Un ID utente è univoco in tutto il sistema ma non in tutto il mondo .

  2. Lo stesso vale per il nome utente : esiste una “radice” per sistema Unix, ma ci sono molte radici nel mondo. Una tabella arcobaleno per “root” varrebbe la pena, poiché potrebbe essere applicata a milioni di sistemi. Peggio ancora, ci sono anche molti “bob” là fuori, e molti non hanno un addestramento sysadmin: le loro password potrebbero essere piuttosto deboli.

  3. L’unicità è anche temporale. A volte, gli utenti cambiano la loro password. Per ogni nuova password , deve essere selezionato un nuovo salt . In caso contrario, un utente malintenzionato ha ottenuto l’hash della vecchia password e l’hash del nuovo potrebbe provare ad attaccare entrambi contemporaneamente.

Usare un sale casuale ottenuto da un PRNG crittograficamente sicuro e imprevedibile può essere una sorta di esagerazione, ma almeno ti protegge in modo definitivo da tutti quei rischi. Non si tratta di impedire all’aggressore di sapere che cos’è un singolo sale, si tratta di non dare loro il bersaglio grosso e grasso che verrà utilizzato su un numero considerevole di potenziali bersagli. La selezione casuale rende gli obiettivi sottili come è pratico.

In conclusione:

Utilizzare un sale ad alta entropia casuale, uniformsmente distribuito. Usa un nuovo salt ogni volta che crei una nuova password o cambi una password. Memorizza il sale insieme alla password con hash. Favorire i sali grandi (almeno 10 byte, preferibilmente 16 o più).

Un sale non trasforma una password errata in una buona password. Si limita a fare in modo che l’attaccante paghi almeno il prezzo di attacco del dizionario per ogni password errata che si rompe.

Fonti utili:
stackoverflow.com: sale non casuale per gli hash delle password
Bruce Schneier: Practical Cryptography (libro)
Matasano Security: basta con le tabelle Rainbow
usenix.org: la cripta Unix utilizza sale dal 1976
owasp.org : Perché aggiungere sale
openwall.com : Sali

Disclaimer:
Non sono un esperto di sicurezza. (Sebbene questa risposta sia stata esaminata da Thomas Pornin )
Se qualcuno dei professionisti della sicurezza ha trovato qualcosa di sbagliato, si prega di commentare o modificare questa risposta wiki.

Da quando Unix è diventato popolare, il modo giusto per memorizzare una password è stato quello di aggiungere un valore casuale (il sale) e cancellarlo. Salva il sale dove puoi arrivare più tardi, ma dove speri che i cattivi non lo capiscano.

Questo ha alcuni buoni effetti. In primo luogo, i cattivi non possono semplicemente creare un elenco di password previste come “Password1”, inserirle in una tabella arcobaleno e passare attraverso il file della password alla ricerca di corrispondenze. Se hai un buon sale a due byte, devono generare 65.536 valori per ogni password prevista, e questo rende la tabella arcobaleno molto meno pratica. In secondo luogo, se riesci a mantenere il sale dei cattivi che stanno guardando il tuo file di password, hai reso molto più difficile calcolare i valori possibili. Terzo, hai reso imansible per i cattivi determinare se una determinata persona usa la stessa password su siti diversi.

Per fare ciò, si genera un sale casuale. Questo dovrebbe generare ogni numero nell’intervallo desiderato con probabilità uniforms. Questo non è difficile; un semplice generatore di numeri casuali congruenziali lineari farà bene.

Se hai calcoli complicati per fare il sale, stai sbagliando. Se lo calcoli in base alla password, lo stai facendo in modo sbagliato. In tal caso, tutto ciò che stai facendo è complicare l’hash e non aggiungere funzionalmente sale.

Nessuno a cui fare affidamento sulla sicurezza si affiderebbe a hide un algoritmo. La crittografia moderna si basa su algoritmi che sono stati ampiamente testati e per essere ampiamente testati devono essere ben noti. In generale, è stato trovato più sicuro usare gli algoritmi standard piuttosto che rotolare il proprio e sperare che sia buono. Non importa se il codice è open source o meno, è ancora spesso ansible per i cattivi analizzare ciò che fa un programma.

È ansible generare un salt casuale per ogni record in fase di esecuzione. Ad esempio, supponiamo che stiate memorizzando le password utente con hash in un database. È ansible generare una stringa casuale di 8 caratteri alfanumerici maiuscoli e minuscoli in fase di esecuzione, anteporre la password, eseguire l’hash di tale stringa e archiviarla nel database. Poiché ci sono 62 8 sali possibili, la generazione di tavole arcobaleno (per ogni sale ansible) sarà proibitivamente costosa; e dal momento che si sta utilizzando un salt unico per ogni record di password, anche se un utente malintenzionato ha generato un paio di tabelle arcobaleno corrispondenti, non sarà comunque in grado di decifrare ogni password.

Puoi modificare i parametri della tua generazione di sale in base alle tue esigenze di sicurezza; ad esempio, è ansible utilizzare un valore più lungo, oppure è ansible generare una stringa casuale che contiene anche segni di punteggiatura, per aumentare il numero di possibili sali.

Utilizzare un generatore di funzioni casuali per generare il sale, e memorizzarlo nel database, fare il sale uno per riga e memorizzarlo nel database.

Mi piace come viene generato il sale nella registrazione di django. Riferimento: http://bitbucket.org/ubernostrum/django-registration/src/tip/registration/models.py#cl-85

salt = sha_constructor(str(random.random())).hexdigest()[:5] activation_key = sha_constructor(salt+user.username).hexdigest() return self.create(user=user, activation_key=activation_key) 

Usa una combinazione di sha generata da un numero casuale e il nome utente per generare un hash.

Sha stesso Sha è noto per essere forte e indistruttibile. Aggiungi più dimensioni per generare il sale stesso, con numero casuale, sha e il componente specifico dell’utente, hai sicurezza indistruttibile!

Nel caso di un’applicazione desktop che crittografa i dati e li invia su un server remoto, come pensi di utilizzare un sale diverso ogni volta?

Utilizzando PKCS # 5 con la password dell’utente, è necessario un sale per generare una chiave di crittografia, per crittografare i dati. So che mantenere il sale hardcoded (offuscato) nell’applicazione desktop non è una buona idea.

Se il server remoto non deve MAI conoscere la password dell’utente, è ansible utilizzare ogni volta un sale diverso? Se l’utente utilizza l’applicazione desktop su un altro computer, come sarà in grado di decrittografare i dati sul server remoto se non ha la chiave (non è codificata nel software)?