Quale tipo di dati utilizzare per il campo password con hash e quale lunghezza?


269

Non sono sicuro di come funzioni l'hashing della password (lo implementerà in seguito), ma ora devo creare lo schema del database.

Sto pensando di limitare le password a 4-20 caratteri, ma come ho capito dopo aver crittografato la stringa hash avrà una lunghezza diversa.

Quindi, come archiviare queste password nel database?


Vedi anche il framework di hashing delle password PHP di Openwall (PHPass). È portatile e indurito contro una serie di attacchi comuni alle password degli utenti. Il tizio che ha scritto il framework (SolarDesigner) è lo stesso tizio che ha scritto John The Ripper e siede come giudice nel concorso Password Hashing . Quindi sa qualcosa o due sugli attacchi alle password.
jww

2
Si prega di non porre un limite massimo alle password. Li stai cancellando, non c'è motivo di archiviazione per un limite superiore. Se sei preoccupato per gli attacchi DoS usando l'hash della password, 1000 o 1024 rappresentano un limite massimo ragionevole.
Iiridayn,

perché limitare la lunghezza della password? Almeno lascia che un utente crei una password di 100 caratteri :)
Andrew

4 caratteri è un limite inferiore piuttosto pericoloso per le password in quanto sono banali da decifrare. Almeno usare 8 ma 14 o 16 è molto meglio.
quikchange

Questa è una domanda molto vecchia con una risposta obsoleta. Vedi la risposta di Gilles per l'aggiornamento.
Kelalaka,

Risposte:


448

Aggiornamento: il semplice utilizzo di una funzione hash non è abbastanza forte per l'archiviazione delle password. Dovresti leggere la risposta di Gilles su questo thread per una spiegazione più dettagliata.

Per le password, utilizzare un algoritmo hash di rafforzamento delle chiavi come Bcrypt o Argon2i. Ad esempio, in PHP, utilizzare la funzione password_hash () , che utilizza Bcrypt per impostazione predefinita.

$hash = password_hash("rasmuslerdorf", PASSWORD_DEFAULT);

Il risultato è una stringa di 60 caratteri simile alla seguente (ma le cifre varieranno, perché genera un unico sale).

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

Utilizzare il tipo di dati SQL CHAR(60)per archiviare questa codifica di un hash Bcrypt. Nota che questa funzione non codifica come una stringa di cifre esadecimali, quindi non possiamo facilmente asimularla per archiviarla in binario.

Altre funzioni hash hanno ancora usi, ma non per l'archiviazione delle password, quindi terrò la risposta originale di seguito, scritta nel 2008.


Dipende dall'algoritmo di hashing che usi. L'hash produce sempre un risultato della stessa lunghezza, indipendentemente dall'input. È tipico rappresentare il risultato hash binario nel testo, come una serie di cifre esadecimali. Oppure puoi usare la UNHEX()funzione per ridurre della metà una stringa di cifre esadecimali.

  • MD5 genera un valore hash a 128 bit. Puoi usare CHAR (32) o BINARY (16)
  • SHA-1 genera un valore hash a 160 bit. Puoi usare CHAR (40) o BINARY (20)
  • SHA-224 genera un valore hash di 224 bit. Puoi usare CHAR (56) o BINARY (28)
  • SHA-256 genera un valore hash a 256 bit. Puoi usare CHAR (64) o BINARY (32)
  • SHA-384 genera un valore hash a 384 bit. Puoi usare CHAR (96) o BINARY (48)
  • SHA-512 genera un valore hash a 512 bit. Puoi usare CHAR (128) o BINARY (64)
  • BCrypt genera un valore hash a 448 bit dipendente dall'implementazione. Potrebbe essere necessario CHAR (56), CHAR (60), CHAR (76), BINARY (56) o BINARY (60)

A partire dal 2015, NIST consiglia di utilizzare SHA-256 o versioni successive per qualsiasi applicazione di funzioni hash che richiedono interoperabilità. Ma NIST non consiglia di utilizzare queste semplici funzioni hash per archiviare le password in modo sicuro.

Gli algoritmi di hashing minori hanno i loro usi (come interni a un'applicazione, non per interscambio), ma sono noti per essere crackabili .


47
@Hippo: Per favore, non usare il nome utente come sale. Genera un sale casuale per utente.
Bill Karwin,

11
Sì, non c'è motivo di non memorizzarlo nella stessa riga. Anche se un attaccante ottiene l'accesso al tuo database, dovrebbe costruire la sua tabella arcobaleno basata su quel sale. E questo è tanto lavoro quanto indovinare semplicemente la password.
Bill Karwin,

5
@SgtPooki: è necessaria un'altra colonna per memorizzare il sale in testo normale. Quindi è possibile eseguire l'hashing della password dell'utente con lo stesso salt quando lo digitano e confrontare il risultato con il digest hash memorizzato nella tabella.
Bill Karwin,

12
Se stai memorizzando il salt nella stessa tabella (o in qualsiasi altra posizione con le stesse autorizzazioni di accesso) non c'è motivo di non utilizzare il nome utente come salt, poiché sarà unico per utente. Tuttavia, qualsiasi sale noto rende l'hash crittograficamente più debole che se non ci fosse sale noto. Un sale aggiunge valore solo se è anche sconosciuto.
fijiaaron,

9
Non capisco l'affare con il sale noto contro sconosciuto. Se stai implementando un sito, è necessario conoscere Salt nella pagina di accesso / script / servizio che sta testando la password. Quindi, voi sostenitori del sale "sconosciuti", supponete che il codice per il processo di accesso sia sconosciuto all'attaccante? Altrimenti - l'attaccante non conoscerà sempre il sale, sia esso casuale, unico, memorizzato insieme alla password con hash o separato?
mattstuehler,

13

Puoi effettivamente usare CHAR(lunghezza dell'hash) per definire il tuo tipo di dati per MySQL perché ogni algoritmo di hashing valuterà sempre lo stesso numero di caratteri. Ad esempio, SHA1restituisce sempre un numero esadecimale di 40 caratteri.


1
SHA-1 non è adatto per le password di hashing.
Gilles 'SO- smetti di essere malvagio' il

10

Utilizzare sempre un algoritmo di hashing della password: Argon2 , scrypt , bcrypt o PBKDF2 .

Argon2 ha vinto la competizione di hashing delle password 2015. Scrypt , bcrypt e PBKDF2 sono algoritmi più vecchi che ora sono considerati meno preferiti, ma comunque fondamentalmente sani, quindi se la tua piattaforma non supporta ancora Argon2, per ora va bene usare un altro algoritmo.

Non archiviare mai una password direttamente in un database. Non crittografarlo, neanche: altrimenti, se il tuo sito viene violato, l'attaccante ottiene la chiave di decrittazione e quindi può ottenere tutte le password. Le password DEVONO essere hash .

Un hash password ha proprietà diverse da un hash tabella hash o un hash crittografico. Non utilizzare mai un normale hash crittografico come MD5, SHA-256 o SHA-512 su una password. Un algoritmo di hashing della password utilizza un salt , che è unico (non utilizzato per nessun altro utente o nel database di qualcun altro). Il sale è necessario affinché gli aggressori non possano semplicemente pre-calcolare gli hash delle password comuni: con un salt, devono riavviare il calcolo per ogni account. Un algoritmo di hashing della password è intrinsecamente lento - il più lento che puoi permetterti. La lentezza fa male all'attaccante molto più di te perché l'attaccante deve provare molte password diverse. Per ulteriori informazioni, vedere Come eseguire l'hashing sicuro delle password .

Un hash password codifica quattro informazioni:

  • Un indicatore di quale algoritmo viene utilizzato. Ciò è necessario per l' agilità : le raccomandazioni crittografiche cambiano nel tempo. Devi essere in grado di passare a un nuovo algoritmo.
  • Un indicatore di difficoltà o durezza. Più alto è questo valore, maggiore è il calcolo necessario per calcolare l'hash. Questo dovrebbe essere un valore di configurazione costante o globale nella funzione di modifica della password, ma dovrebbe aumentare nel tempo man mano che i computer diventano più veloci, quindi è necessario ricordare il valore per ciascun account. Alcuni algoritmi hanno un singolo valore numerico, altri hanno più parametri lì (ad esempio per ottimizzare l'utilizzo della CPU e l'utilizzo della RAM separatamente).
  • Il sale. Poiché il sale deve essere univoco a livello globale, deve essere archiviato per ogni account. Il salt dovrebbe essere generato casualmente ad ogni cambio di password.
  • L'hash corretto, ovvero l'output del calcolo matematico nell'algoritmo di hashing.

Molte librerie includono una coppia di funzioni che compatta convenientemente queste informazioni come una singola stringa: una che prende l'indicatore dell'algoritmo, l'indicatore di durezza e la password, genera un salt casuale e restituisce la stringa hash completa; e uno che accetta una password e l'intera stringa hash come input e restituisce un valore booleano che indica se la password era corretta. Non esiste uno standard universale, ma è una codifica comune

$ algoritmo $ parametri $ salt $ output

dove algorithmè un numero o una stringa alfanumerica breve che codifica la scelta dell'algoritmo, parametersè una stringa stampabile salte outputsono codificati in Base64 senza terminare =.

16 byte sono sufficienti per il sale e l'output. (Vedi ad esempio i consigli per Argon2 .) Codificato in Base64, composto da 21 caratteri ciascuno. Le altre due parti dipendono dall'algoritmo e dai parametri, ma sono tipici 20–40 caratteri. Questo è un totale di circa 82 caratteri ASCII ( CHAR(82)e non è necessario Unicode), a cui dovresti aggiungere un margine di sicurezza se pensi che sarà difficile allargare il campo in seguito.

Se si codifica l'hash in un formato binario, è possibile ridurlo a 1 byte per l'algoritmo, 1–4 byte per la durezza (se si codificano alcuni parametri) e 16 byte ciascuno per il sale e l'output , per un totale di 37 byte. Pronunciare 40 byte ( BINARY(40)) per avere almeno un paio di byte di riserva. Si noti che si tratta di byte a 8 bit, non di caratteri stampabili, in particolare il campo può includere byte null.

Si noti che la lunghezza dell'hash non è completamente correlata alla lunghezza della password.


9

Si potrebbe trovare questo articolo di Wikipedia su salatura pena . L'idea è quella di aggiungere un po 'di dati per randomizzare il valore dell'hash; questo proteggerà le tue password dagli attacchi del dizionario se qualcuno ottiene l'accesso non autorizzato agli hash delle password.


2
Vale davvero la pena (+1), ma non risponde alla domanda! (-1)
Bill Karwin,

3
Sì, ma sicuramente rilevante in questo contesto (+1)
Treb,

7

Come una stringa di lunghezza fissa (VARCHAR (n) o comunque chiamata da MySQL). Un hash ha sempre una lunghezza fissa di, ad esempio, 12 caratteri (a seconda dell'algoritmo di hash che usi). Quindi una password di 20 caratteri verrebbe ridotta a un hash di 12 caratteri e una password di 4 caratteri produrrebbe anche un hash di 12 caratteri.


3
'o comunque MySQL lo chiama' - MYSQL lo chiama CHAR. Questo tipo è per un valore di lunghezza fissa. Quindi penso che CHAR sia un tipo migliore di VARCHAR.
t298712383,

4

È necessario utilizzare TEXT(memorizzazione di un numero illimitato di caratteri) per motivi di compatibilità futura. Gli algoritmi di hash (devono) diventare più forti nel tempo e quindi questo campo del database dovrà supportare più caratteri nel tempo. Inoltre, a seconda della strategia di migrazione, potrebbe essere necessario archiviare hash nuovi e vecchi nello stesso campo, pertanto non è consigliabile fissare la lunghezza a un tipo di hash.


3

Dipende molto dall'algoritmo di hashing che stai utilizzando. La lunghezza della password ha poco a che fare con la lunghezza dell'hash, se ricordo bene. Cerca le specifiche dell'algoritmo di hashing che stai utilizzando, esegui alcuni test e tronca appena sopra.


3

Gli hash sono una sequenza di bit (128 bit, 160 bit, 256 bit, ecc., A seconda dell'algoritmo). La colonna deve essere di tipo binario, non di testo / carattere, se MySQL lo consente (il tipo di dati di SQL Server è binary(n)o varbinary(n)). Dovresti anche salare gli hash. I sali possono essere di testo o binari e avrai bisogno di una colonna corrispondente.


La giustizia qui è completamente corretta - MySQL li memorizzerà come valori numerici e renderà la ricerca su questa colonna molto più efficiente rispetto a una corrispondenza di stringhe, tuttavia i sali non dovrebbero essere archiviati nel database accanto ai dati salati - ciò elimina la sicurezza che i sali forniscono .
Tony Maro,

6
I sali non sono segreti. L' unico segreto è la password. Basta assicurarsi che ogni nuova password ottenga un nuovo sale. Ogni volta che l'utente cambia la sua password, il sistema dovrebbe generare un nuovo salt per quella password. I sali devono essere lunghi e casuali, ad esempio 16 byte generati da un PRNG crittograficamente sicuro.
yfeldblum,

1
@TonyMaro Non sono sicuro che una stringa di password corrisponda a livello SQL sia una buona strategia. In altre parole, non dovresti cercare una password nel tuo database, ma recupera l'utente in base al suo nome utente e confronta le password nel codice, piuttosto che in SQL.
Bart il

1

Ho sempre testato per trovare la lunghezza della stringa MAX di una stringa crittografata e impostarla come lunghezza del carattere di un tipo VARCHAR. A seconda di quanti record avrai, potrebbe davvero aiutare la dimensione del database.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.