2009-03-05 15 views
138

Ho una semplice domanda, che si è verificato quando ho voluto memorizzare il risultato di un hash SHA1 in un database MySQL:valori hash Memorizzazione SHA1 in MySQL

Quanto tempo dovrebbe il campo VARCHAR in cui ho memorizzare il il risultato di hash?

+8

Se hai appena Googled SHA1 click im senti fortunato e si dovrebbe essere su wikipedia dove si può trovare è sempre 160 bit. –

risposta

283

Vorrei utilizzare VARCHAR per dati di lunghezza variabile, ma non con dati di lunghezza fissa. Poiché un valore SHA-1 è sempre lungo 160 bit, lo VARCHAR sprecherebbe solo an additional byte for the length of the fixed-length field.

E inoltre non memorizzare il valore restituito da SHA1. Perché usa solo 4 bit per carattere e quindi avrebbe bisogno di 160/4 = 40 caratteri. Ma se usi 8 bit per carattere, avrai solo bisogno di un campo lungo 160/8 = 20 caratteri.

Quindi si consiglia di utilizzare BINARY(20) e UNHEX function per convertire il valore SHA1 in binario.

Ho confrontato i requisiti di archiviazione per BINARY(20) e CHAR(40).

CREATE TABLE `binary` (
    `id` int unsigned auto_increment primary key, 
    `password` binary(20) not null 
); 
CREATE TABLE `char` (
    `id` int unsigned auto_increment primary key, 
    `password` char(40) not null 
); 

Con milioni di record binary(20) prende 44.56M, mentre char(40) prende 64.57M. InnoDB motore.

+2

In PostgreSQL, questo si tradurrebbe nell'uso di un campo bytea, giusto? – mvexel

+9

@ Gumbo: Lei signore, credo, l'ho già fatto prima! :) –

+0

La soluzione è ottima, ma c'è un altro punto da usare char (40) con hex1 sha1 - questo è molto più usato, e ci saranno meno problemi di conversione in un codice applicativo. –

36

Un hash SHA1 è lungo 40 caratteri!

+80

Nella codifica esadecimale ... –

6

La dimensione di uscita di sha1 è 160 bit. Quale è 160/8 == 20 caratteri (se si utilizzano caratteri a 8 bit) o ​​160/16 = 10 (se si utilizzano caratteri a 16 bit).

+0

Assunzione di caratteri binari a 8 bit. 40 caratteri se memorizzati come esadecimale. – Tyzoid

3

Quindi la lunghezza è compresa tra 10 caratteri a 16 bit e 40 cifre esadecimali.

In ogni caso, decidere il formato che si intende memorizzare e impostare il campo su una dimensione fissa in base a tale formato. In questo modo non avrai nessuno spazio sprecato.

2

È possibile continuare a utilizzare VARCHAR nei casi in cui non si memorizza sempre un hash per l'utente (ad esempio account di autenticazione/URL di accesso dimenticato). Una volta che un utente ha autenticato/modificato le proprie informazioni di accesso, non dovrebbe essere in grado di utilizzare l'hash e non dovrebbe avere motivo di farlo. È possibile creare una tabella separata per memorizzare hash temporanei -> associazioni utente che potrebbero essere eliminate ma non credo che la maggior parte delle persone si preoccupi di farlo.

2

Se è necessario un indice sulla colonna sha1, suggerisco CHAR (40) per motivi di prestazioni. Nel mio caso la colonna sha1 è un token di conferma dell'email, quindi nella pagina di destinazione la query entra solo con il token. In questo caso CHAR (40) con INDICE, a mio parere, è la scelta migliore :)

Se si desidera adottare questo metodo, ricordarsi di lasciare $ raw_output = false.

+1

Perché non indicizzare BINARY (20)? Non sarebbe altrettanto veloce e metà delle dimensioni? – nickdnk

+0

Beh, questo ~ 5 anni fa, ma penso che mi stavo riferendo al fatto che hai ancora bisogno di annullare ciò che aggiunge un po 'di carico (+ rende l'applicazione più difficile da mantenere e meno portabile?). Dipende anche dal tuo hardware, se hai meno memoria ed è lento probabilmente anche meglio attenersi al binario (20) altrimenti direi char (40). Difficile da dire senza eseguire alcuni test con la lingua e l'hardware che useresti e vedere cosa ti si addice meglio. –

+1

Suppongo che se stai facendo qualcosa di diverso da selezionare da dove unhex (hash) = hash per recuperare una singola riga, allora forse hai ragione. Ma mantenere l'indice bufferizzato richiederà il doppio della memoria in questo modo. – nickdnk

8

Reference taken from this blog:

Ecco un elenco di hashing algoritmo insieme con le sue dimensioni richiedono bit:

  • MD5 = valore hash a 128 bit.
  • SHA1 = valore hash a 160 bit.
  • SHA224 = valore hash 224 bit.
  • SHA256 = valore hash a 256 bit.
  • SHA384 = valore di hash 384 bit.
  • SHA512 = valore di hash a 512 bit.

Creato tavolo un campione con richiede CHAR (n):

CREATE TABLE tbl_PasswordDataType 
(
    ID INTEGER 
    ,MD5_128_bit CHAR(32) 
    ,SHA_160_bit CHAR(40) 
    ,SHA_224_bit CHAR(56) 
    ,SHA_256_bit CHAR(64) 
    ,SHA_384_bit CHAR(96) 
    ,SHA_512_bit CHAR(128) 
); 
INSERT INTO tbl_PasswordDataType 
VALUES 
(
    1 
    ,MD5('SamplePass') 
    ,SHA1('SamplePass') 
    ,SHA2('SamplePass',224) 
    ,SHA2('SamplePass',256) 
    ,SHA2('SamplePass',384) 
    ,SHA2('SamplePass',512) 
); 
+5

Please, _please_, _ ** please ** _ in realtà non memorizzano password come questa. –

+0

Hey berry, puoi spiegare il tuo PERCHE '?in dettaglio – Anvesh

+2

La memorizzazione di semplici hash di password rende molto più semplice l'estrazione delle password se il database è compromesso rispetto all'utilizzo di un hash di password salato (eventualmente allungato). Lettura suggerita: https://paragonie.com/blog/2016/02/how-safely-store-password-in-2016 – matt