Bcrypt
Genera un hash bcrypt o verifica una password contro uno senza uscire dal browser: scegli il costo e la variante $2a$, $2b$ o $2y$, e scomponi qualsiasi hash.
Nulla di ciò che scrivi qui lascia questo browser. Il lavoro gira in un Web Worker di questa scheda: apri il tuo pannello di rete e guarda, mentre calcola non esce nemmeno una richiesta.
Genera un hash
Una password, un costo e una variante. Il sale viene estratto nuovo da questo browser a ogni esecuzione, quindi la stessa password dà ogni volta un hash diverso: è bcrypt che funziona, non un difetto.
Verifica una password contro un hash
Un hash incollato viene scomposto subito, senza password e senza attesa. Aggiungi la password per sapere se corrisponde. Un hash non si può invertire, né qui né altrove.
Che cosa c’è davvero dentro un hash bcrypt
Un hash bcrypt è un’unica stringa di sessanta caratteri, e ogni sua parte è in chiaro. Non c’è niente di segreto tranne la password che l’ha prodotto, e quella lì dentro non c’è affatto. Smontarlo non richiede una chiave, né una password, né alcun calcolo: questa pagina lo fa nell’istante in cui ne incolli uno.
- La variante, il campo con cui la stringa si apre: $2b$, $2a$ o $2y$. Dice secondo le regole di chi è stato prodotto l’hash.
- Il costo, scritto con esattamente due cifre: da 04 a 31. È un esponente, quindi costo 12 vuol dire 2^12 — 4.096 — round di stiramento della chiave, e il costo 13 è il doppio del lavoro del 12 anziché un tredicesimo in più.
- Il sale, ventidue caratteri: sedici byte casuali, conservati in chiaro accanto alla risposta che hanno salato.
- Il digest, gli ultimi trentuno caratteri: ventitré byte di output. È l’unica parte che dipende dalla password, e non è l’hash — l’hash è la stringa intera.
L’alfabeto da cui escono quei caratteri è quello di bcrypt, e non è il Base64 standard: va ./A-Za-z0-9, quindi un punto e una barra lo aprono dove Base64 mette il più e la barra in fondo. Decodificarlo con un normale decodificatore Base64 restituisce byte sbagliati anziché un errore, ed è un modo classico di perdere un pomeriggio.
Il limite di settantadue byte si conta in byte, e la cosa pesa
bcrypt legge al massimo settantadue byte di una password e ignora tutto ciò che viene dopo. Non settantadue caratteri — settantadue byte di UTF-8, quindi quanti caratteri siano dipende da quanto costano le lettere di una lingua: le ventisei lettere latine senza segni costano un byte ciascuna, e ogni altra lettera costa di più. In italiano la differenza è piccola e reale insieme: ogni vocale accentata — à, è, é, ì, ò, ù — costa due byte, quindi una password con qualche accento arriva al limite qualche carattere prima dei settantadue. Una fatta solo di quelle lettere lo raggiungerebbe a trentasei.
- L’ASCII costa un byte per carattere, quindi chi scrive in inglese arriva al limite a settantadue caratteri e non ci arriva quasi mai.
- L’ebraico, l’arabo, il russo e il greco costano due byte per lettera, quindi il limite arriva a trentasei caratteri.
- Il giapponese, il coreano e il cinese ne costano tre, quindi arriva a ventiquattro.
- La maggior parte delle emoji costa quattro, e molte di quelle che la gente scrive davvero sono più punti di codice uniti insieme, quindi una manciata è già tutto il budget.
Il contatore di byte sotto il campo della password è lì perché questa sia una cosa che puoi vedere avvicinarsi anziché scoprire dopo. E il taglio cade sul byte, non sul carattere, esattamente come fa ogni implementazione di riferimento — quindi un carattere multibyte a cavallo del confine perde una parte di sé e conserva il resto. È il comportamento compatibile e non un difetto, e questa pagina lo dice quando succede.
E ora la parte che spiega tutto il resto: il troncamento è invisibile nella risposta. La programmazione della chiave mescola nel proprio stato esattamente settantadue byte di chiave e non ne riavvolge mai una più lunga, quindi calcolare l’hash di una password da cento byte e calcolare quello dei suoi primi settantadue byte danno lo stesso identico digest. Non c’è nulla che un’implementazione possa rilevare né nulla che possa segnalare, ed è per questo che nessuna libreria solleva un errore e per questo due password lunghe diverse che coincidono nei primi settantadue byte corrispondono entrambe allo stesso hash conservato. Nemmeno questa pagina può rifiutare una password lunga — se stai verificando contro un hash che un sistema reale ha prodotto troncando, la risposta ti serve — quindi te la dà e ti dice che cosa è stato tagliato.
La variante cambia il prefisso e non il digest
La variante sembra un numero di versione e non lo è. Le tre che questo strumento scrive non sono ordinate, nessuna sostituisce le altre, e sceglierne una è una decisione di compatibilità anziché di sicurezza.
- $2b$ è quella su cui si è fermato OpenBSD ed è quella che oggi emettono Python, Node e Go. Qui è la predefinita ed è la risposta giusta quando nulla ne impone un’altra.
- $2a$ è la più vecchia, e alcuni impianti Java e Spring Security di lunga data si aspettano ancora di vederla.
- $2y$ è quella che scrivono password_hash di PHP e quindi Laravel, perciò un hash incollato in quel mondo di solito la vuole.
A separare le tre è come trattano una chiave più lunga di 255 byte, e bcrypt ha già smesso di leggere a settantadue — quindi nessuna password che tu possa scrivere qui arriva a quella differenza. Per tutto ciò che questo strumento riceverà mai, le tre producono gli stessi ventitré byte e si distinguono solo nei quattro caratteri iniziali. Cambia la variante e il digest non si muove.
Ne esistono altre due e questo strumento le nomina anziché calcolarle. $2x$ non è una correzione: Openwall la coniò apposta per riprodurre un bug di estensione del segno, in modo che gli hash fatti dal codice difettoso si potessero ancora verificare, e implementarla qui vorrebbe dire mettere un difetto noto dentro lo strumento. $2$ è l’originale, di prima che alla chiave venisse aggiunto il byte zero finale. Nessuna delle due è emessa da qualcosa di attuale; se ne hai una fra le mani, è uscita da un sistema tanto vecchio che la variante è il minore dei tuoi ritrovamenti.
Il costo, e quanto costa sulla tua stessa macchina
Il costo è il fattore di lavoro, da 4 a 31, ed è un esponente: ogni passo raddoppia il tempo. È in questo che consiste bcrypt per intero. L’hash di una password deve essere lento, perché chi attacca con una tabella rubata paga lo stesso prezzo a ogni tentativo, e raddoppiare il costo dimezza il numero di tentativi al secondo che i suoi soldi gli comprano.
Quanto prenda davvero un dato costo è un fatto sulla macchina che lo esegue, non un numero che si possa scrivere una volta per tutte: un telefono e un server distano due ordini di grandezza. Perciò questa pagina misura anziché citare: al caricamento esegue un hash breve sul tuo dispositivo e da lì estrapola, ed è per questo che la stima accanto al controllo del costo resta vuota un istante e poi compare. Oltre qualche secondo chiede prima di partire, così una cifra digitata male non si legge come una pagina bloccata.
Per scegliere un numero: 12 è quello che emettono in modo predefinito Laravel e il pacchetto bcrypt di Python ed è oggi una soglia ragionevole in produzione. I costi più bassi servono per le fixture di test, dove una suite che semina cinquanta utenti non dovrebbe spendere un secondo a utente. I costi sopra il 15 conviene misurarli contro il traffico reale di accesso prima di pubblicarli, perché anche ogni accesso ne paga il prezzo.
# Apache: scrivere una riga htpasswd al costo 12
htpasswd -nbBC 12 alice "correct horse battery staple"
# PHP e Laravel: password_hash emette $2y$
php -r 'echo password_hash("correct horse battery staple", PASSWORD_BCRYPT);'
# Python: il pacchetto bcrypt emette $2b$, e gensalt prende il costo
python -c "import bcrypt; print(bcrypt.hashpw(b'correct horse battery staple', bcrypt.gensalt(12)))"Il sale, e quando un hash fatto qui non è da conservare
Il sale è sedici byte casuali estratti nuovi per ogni hash, ed è conservato in chiaro dentro la stringa stessa. Non è un segreto e non è mai stato pensato per esserlo: il suo compito è far sì che due password identiche producano due hash senza alcuna relazione, così che una tabella rubata non si possa attaccare un dizionario precalcolato alla volta.
Per questo anche la stessa password ti dà qui un hash diverso ogni volta che premi il pulsante. Non è un guasto e la risposta di prima non è scaduta: un sale nuovo è bcrypt che funziona. Ognuno di quegli hash corrisponde alla password, perché il sale viaggia dentro la stringa che viene verificata.
Il campo avanzato del sale esiste per un solo compito: riprodurre esattamente l’hash di qualcun altro, così da poter confrontare due implementazioni. Incollaci dentro un hash intero e il costo e la variante lo seguono da soli, così la password giusta riproduce l’input carattere per carattere. Tutto ciò che produci in quel modo serve al confronto e non alla conservazione: un sale usato due volte è un sale che ha smesso di fare il suo lavoro.
Un hash bcrypt non si può invertire
Su pagine come questa la gente arriva cercando un modo per decifrare un hash bcrypt. Non ce n’è uno, e il motivo non è che sia difficile: la password non è nella stringa. Sessanta caratteri portano una variante, un costo, sedici byte casuali e ventitré byte di output, e nessuna combinazione di tutto ciò contiene una password di qualsivoglia lunghezza. Non è stato cifrato nulla, quindi non c’è nulla da decifrare.
Quello che un sito può fare — ed è quello che fanno quelli che pubblicizzano la decifrazione — è indovinare. Si prende un elenco di password comuni, si calcola l’hash di ciascuna contro il tuo sale e al tuo costo, e si guarda se qualcuna corrisponde. bcrypt è progettato per rendere caro proprio questo, ed è a questo che serve il costo, e questo strumento non lo offre in nessuna forma.
La versione onesta di quella domanda di solito è un’altra, e una risposta ce l’ha: che cosa c’è in questa stringa, e proprio questa password la produce? Sono entrambe su questa pagina. Incolla l’hash per vedere tutto ciò che porta, e aggiungi una password per avere un sì o un no.
Domande frequenti
- La mia password viene inviata a un server?
- No. Tutto avviene in questa scheda del browser: l’hashing gira in un Web Worker sulla tua macchina, la password non entra mai nell’URL e non viene scritto nulla nella memoria del browser. Apri il tuo pannello di rete, scrivi una password e premi il pulsante: non esce nemmeno una richiesta. È questa la differenza fra questa pagina e i due siti che le stanno sopra nei risultati per la stessa domanda.
- Un hash bcrypt si può decifrare e tornare alla password?
- No, e non perché sia difficile. La password non è nella stringa: quello che c’è è una variante, un costo, un sale e ventitré byte di output, e nulla di tutto ciò contiene l’input. Chi si offre di decifrarne uno sta tirando a indovinare password comuni contro il tuo sale, che è proprio ciò che bcrypt è progettato per rendere lento.
- Perché la stessa password dà un hash diverso ogni volta?
- Perché a ogni esecuzione viene estratto un sale casuale nuovo, e il sale fa parte della stringa. Ognuno di quegli hash corrisponde alla stessa password — chi verifica legge il sale dall’hash che incolli, quindi non ha bisogno di sapere quale esecuzione l’ha prodotto.
- La mia password è stata tagliata a settantadue byte. Perché non c’è stato un errore?
- Perché non c’è nulla da rilevare. bcrypt mescola nel proprio stato esattamente settantadue byte di chiave e non legge mai oltre, quindi una password lunga e i suoi primi settantadue byte producono lo stesso digest: il troncamento non lascia traccia che una libreria possa notare. Questa pagina ti dice che è successo, che è il massimo che un’implementazione possa onestamente fare.
- Perché la mia password ha toccato il limite a trentasei caratteri?
- Perché il limite è di settantadue byte anziché di settantadue caratteri, e le lettere dell’ebraico, dell’arabo, del russo e del greco costano due byte ciascuna in UTF-8. Quelle del giapponese, del coreano e del cinese ne costano tre, quindi lì il limite arriva a ventiquattro caratteri, e la maggior parte delle emoji ne costa quattro. In italiano vale lo stesso per ogni vocale accentata: una password fatta solo di à, è, é, ì, ò e ù si taglia a trentasei. Il contatore sotto il campo mostra i byte mentre scrivi.
- Quale variante devo scegliere?
- Quella che si aspetta il sistema in cui la incollerai: $2y$ per PHP e Laravel, $2a$ per Spring Security più vecchi, $2b$ in tutto il resto. È una decisione di compatibilità anziché di sicurezza: a qualunque lunghezza si possa dare a questo strumento, le tre producono digest identici e si distinguono solo in quei quattro caratteri iniziali.
- Che costo devo usare?
- 12 è il valore predefinito più diffuso ed è una soglia ragionevole in produzione. Usa un costo basso per le fixture di test, così che la tua suite non paghi cinquanta volte lo stiramento della chiave, e misura qualunque valore sopra il 15 contro il traffico reale di accesso prima di pubblicarlo, perché ogni accesso riuscito paga lo stesso prezzo di chi attacca.
- Un hash fatto qui si può mettere in una tabella utenti vera?
- Per popolare un database, scrivere una fixture o aggiungere una riga htpasswd, sì: il sale viene dalla sorgente crittografica di casualità del tuo browser. Ma questa è una pagina di lavoro anziché un servizio di credenziali: se il sale lo scrivi tu, il risultato smette di essere sicuro da conservare — cosa che la pagina dice sul momento — e una password che vale la pena proteggere si conia meglio là dove andrà a vivere.
- Perché il mio hash comincia con $2y$ se il codice che l’ha fatto dice bcrypt?
- Perché password_hash di PHP scrive $2y$, e Laravel è costruito su di esso. È lo stesso algoritmo di $2b$; la variante registra quale implementazione ha scritto la stringa. Un verificatore che la rifiuta sta rifiutando la variante, non fallendo il confronto con la password.
- Ho incollato un hash e dice che il sale è scritto in un altro modo. È rotto?
- No. Ventidue caratteri possono codificare più bit di quanti ne servano a sedici byte, quindi quattro bit finali vengono scartati e certi sali hanno più di una scrittura che decodifica negli stessi byte. Sistemi reali ne hanno emessi, perciò questa pagina legge un hash simile anziché rifiutarlo, e ti dice qual è la scrittura canonica.
Strumenti correlati
- Decodificatore / verificatore JWT
Decodifica e verifica i JSON Web Token — firma e claim.
- Generatore di hash
MD5, SHA-1, SHA-256, SHA-384 e SHA-512 insieme.
- Decodificatore di certificati e PEM
Leggi un certificato X.509 o una CSR senza OpenSSL.
- Generatore HMAC
Firma un messaggio con una chiave, o verifica la firma di un webhook.