Generatore di token

Genera segreti dal generatore crittografico del browser — hex, base64url o un alfabeto tuo, e passphrase EFF — con l’entropia in bit.

Generazione…
Entropia192.0 bit

Tempo medio per trovarlo, a tre velocità di tentativo. La distanza fra loro è maggiore di qualsiasi differenza faccia il segreto stesso.

  • Contro un accesso che limita i tentativi — 10 tentativi/s10^49 anni
  • Contro un hash lento trapelato (bcrypt, argon2) — 10⁴/s10^46 anni
  • Contro un hash veloce trapelato (SHA-256, MD5) — 10¹²/s10^38 anni

Estrazione da 64 caratteri, quindi ognuno porta 6.00 bit.

Che cosa fa questo strumento

Produce segreti: valori la cui unica difesa è che nessuno possa indovinarli. Scegli un alfabeto e una lunghezza per una chiave API o una password di database, oppure passa a una passphrase estratta da un elenco pubblicato per qualcosa che una persona dovrà digitare. Ogni risultato è generato nel tuo browser e mostrato con l’unico numero che ne descrive onestamente la forza.

È un mestiere diverso da quello del generatore di UUID di questo sito. Un UUID deve essere unico, perché due record non collidano mai; un segreto dev’essere inindovinabile, che è un requisito più forte e un guasto diverso. Un identificatore prevedibile è innocuo. Un segreto prevedibile è una porta aperta.

Da dove viene la casualità

Tutto qui attinge a crypto.getRandomValues, il generatore di casualità crittograficamente sicuro del browser, alimentato dal serbatoio di entropia del sistema operativo: la stessa fonte da cui attingono openssl rand e /dev/urandom.

L’alternativa, Math.random, non è una funzione di sicurezza e non ha mai preteso di esserlo. È un generatore pseudocasuale veloce con uno stato interno piccolo, e in ogni motore attuale quello stato si può ricavare da una breve serie di uscite: da lì in poi ogni valore passato e futuro è noto. Un token costruito così sembra casuale esattamente come uno vero; la differenza salta fuori solo quando qualcuno si prende la briga di guardare.

È lecito chiedersi se una pagina web sia il posto giusto per generare un segreto di produzione. La generazione in sé è solida: è il CSPRNG della piattaforma, la pagina è statica e nulla viene trasmesso. Le parti su cui riflettere sono quelle attorno — un segreto che passa dagli appunti può essere leggibile da altre applicazioni, e uno incollato in un terminale di solito finisce nella cronologia della shell. Sono le stesse considerazioni di qualunque altro metodo.

La distorsione nascosta nell’implementazione ovvia

Trasformare byte casuali in caratteri sembra una riga sola: prendi un byte, fanne il modulo rispetto alla dimensione dell’alfabeto, indicizza. È sottilmente sbagliato per ogni alfabeto la cui dimensione non divida 256 in modo esatto, e l’uscita non ne dà alcun segno.

Con 62 caratteri alfanumerici la divisione non è esatta: 62 sta in 256 quattro volte e ne avanzano 8. Quegli 8 valori di byte avanzati — da 248 a 255 — si ripiegano sui primi 8 caratteri dell’alfabeto, sicché ciascuno di essi riceve cinque possibilità su 256 mentre gli altri ne ricevono quattro. I primi otto caratteri risultano circa il 25% più probabili degli altri.

Il rimedio è il campionamento con rifiuto: scartare un’estrazione che cade nella coda avanzata ed estrarre di nuovo, invece di ripiegarla dentro. Costa circa un’estrazione in più ogni trentadue per un alfabeto di 62 caratteri e nulla del tutto per hex o base64url, le cui dimensioni sono potenze di due e che quindi non hanno coda. Questo strumento rifiuta; l’effetto non si vede in nessun token preso da solo, ed è proprio per questo che vale la pena dirlo.

L’entropia, l’unica misura onesta

L’entropia in bit dice quanto è grande lo spazio dei segreti ugualmente probabili: n bit significano 2^n possibilità. È additiva e facile da confrontare, e non dice nulla su quanto in fretta qualcuno possa percorrere quello spazio — il che è un pregio, perché quella parte dipende da cose che un generatore non può sapere.

L’aritmetica è deliberatamente semplice. Ogni carattere apporta log2(dimensione dell’alfabeto) bit e ogni parola apporta log2(dimensione dell’elenco), quindi:

  • Un carattere hex vale 4 bit, quindi un token hex di 32 caratteri è esattamente 128 bit: una chiave AES-128 scritta per esteso.
  • Un carattere base64url vale 6 bit, quindi 22 caratteri superano i 128 bit e 43 superano i 256.
  • Un carattere alfanumerico vale circa 5,95 bit; escludere i somiglianti porta l’alfabeto a 58 e il carattere a 5,86, il che costa all’incirca un carattere di lunghezza ogni dodici.
  • Una parola dell’elenco lungo della EFF vale 12,925 bit, perché l’elenco ha 7776 voci, cioè 6^5: cinque lanci di dado.
  • Una parola dell’elenco corto vale 10,34 bit, su 1296 voci, cioè 6^4.

Un obiettivo consueto sono 128 bit, il punto in cui la forza bruta smette di essere una strategia anziché limitarsi a essere costosa. Sono 32 caratteri hex, 22 caratteri base64url, o 10 parole dall’elenco lungo della EFF.

Perché non c’è un unico «tempo per craccarlo»

Un segreto non ha un tempo di craccatura. Ce l’ha la coppia formata dal segreto e da ciò che lo custodisce, e il custode pesa molto più del segreto. Lo stesso valore che attraverso un modulo di accesso richiederebbe più dell’età dell’universo cade in un pomeriggio se era conservato come uno SHA-256 senza sale e il database è trapelato.

Perciò si mostrano tre velocità invece di un numero, ciascuna col suo nome:

  • Dieci tentativi al secondo, contro un accesso che limita la frequenza. È il tetto realistico per chi debba passare dal tuo servizio.
  • Diecimila tentativi al secondo, contro un hash di password trapelato e costruito per essere lento: bcrypt a un costo moderno, o argon2. Quella lentezza è tutto lo scopo di quelle funzioni.
  • Mille miliardi di tentativi al secondo, contro un hash trapelato che non era mai stato pensato per le password. SHA-256 e MD5 sono progettati per essere veloci, e un banco di GPU lo è enormemente.

Le velocità sono arrotondate a potenze di dieci di proposito. Qualcosa di più preciso suggerirebbe la misura di un attaccante particolare, quando l’informazione utile sono gli undici ordini di grandezza fra la prima riga e l’ultima. Se un segreto sta comodo in tutte e tre, la questione è chiusa senza bisogno delle cifre esatte.

Ogni cifra è la media, cioè metà dello spazio e non tutto: una ricerca trova la risposta a metà strada in media. E oltre il milione di anni la risposta è data come ordine di grandezza, perché «quattrocentomila miliardi di anni» non è una durata che qualcuno possa confrontare. L’universo ha circa 10^10 anni, il che offre un riferimento utile per le righe che arrivano tanto lontano.

Le passphrase e da dove viene davvero la loro forza

Una passphrase è forte per una sola ragione: più parole sono state scelte a caso da un elenco grande. Non è forte perché è lunga, né perché somiglia a una lingua. Sei parole a caso da un elenco di 7776 valgono circa 77 bit; sei parole pensate da una persona valgono molto meno, perché le persone non scelgono in modo uniforme e un attaccante sa delle frasi comuni esattamente quanto ne sai tu.

I due elenchi qui vengono dalla EFF e sono gli elenchi diceware pubblicati, scaricati senza modifiche. Non sono elenchi messi insieme qui, e la cosa conta: un elenco di parole inventato ha dimensione ignota, sovrapposizione ignota con altri elenchi e nessun modo di verificare l’entropia che gli si attribuisce.

  • L’elenco lungo ha 7776 parole, una per ogni lancio di cinque dadi, e dà 12,925 bit per parola.
  • L’elenco corto ha 1296 parole, una per ogni lancio di quattro dadi, e dà 10,34 bit per parola. Le sue parole sono più corte — nessuna supera le cinque lettere — il che ne facilita la digitazione al prezzo di più parole per la stessa forza.

Una parola ripetuta in una passphrase non è un difetto e qui non viene riestratta. Ogni estrazione è indipendente, quindi una data coppia di parole è esattamente probabile quanto ogni altra; rifiutare le ripetizioni restringerebbe lo spazio delle passphrase possibili e le renderebbe un po’ più deboli, non più forti.

Entrambi gli elenchi della EFF contengono una manciata di voci col trattino: t-shirt, yo-yo, drop-down, felt-tip. Se anche il separatore è un trattino, una passphrase che ne contenga una non si può ridividere nelle sue parole senza ambiguità. È un problema di presentazione e non di sicurezza, e scegliere uno spazio o un punto come separatore lo evita del tutto.

Le opzioni che costano entropia, e quella che non ne costa

Escludere i caratteri somiglianti scambia forza con leggibilità, e lo scambio è visibile. Togliere 0, O, I e l porta l’alfabeto alfanumerico da 62 a 58 caratteri — che è, esattamente, l’alfabeto base58 usato da Bitcoin, e per la stessa ragione. Ogni carattere scende da 5,95 a 5,86 bit, quindi un token ha bisogno di circa un carattere in più ogni dodici per restare altrettanto forte. Di solito ne vale la pena per qualunque cosa una persona debba leggere a schermo e digitare altrove.

L’opzione è offerta solo dove significa qualcosa. Hex e base64url sono codifiche, non insiemi di caratteri: i loro alfabeti sono fissati da una specifica, e un hex senza 0 non è più hex — nulla saprebbe decodificarlo.

Mettere l’iniziale maiuscola a ogni parola di una passphrase non aggiunge assolutamente nulla, e qui il numero della forza deliberatamente non si muove quando lo attivi. È la stessa trasformazione applicata ogni volta, quindi non crea neppure una possibilità nuova: un attaccante che sappia che la frase è capitalizzata sta esattamente dove era partito. L’opzione esiste perché ci sono campi password che pretendono ancora una maiuscola, non perché aiuti.

Scegliere la lunghezza

Per tutto ciò che maneggia una macchina — chiavi API, token di sessione, segreti di webhook, password di database — non c’è ragione di essere parsimoniosi. 32 caratteri hex o 22 base64url danno 128 bit, e andare oltre costa solo byte in un file di configurazione.

Per tutto ciò che digita una persona il vincolo è diverso e una passphrase è di solito la forma migliore. Sei parole dall’elenco lungo sono più forti di una password casuale di dodici caratteri e assai più facili da azzeccare al primo tentativo, il che conta più di quanto sembri: un segreto che la gente sbaglia a digitare è un segreto che la gente si annota.

Per un codice numerico la lettura onesta è che quattro cifre sono 13 bit e si esauriscono in secondi contro qualunque cosa non limiti la frequenza. Un PIN è sicuro soltanto grazie alla politica di blocco che lo circonda, mai per la propria forza.

Domande frequenti

Quanto dev’essere lunga una chiave API?
Punta a 128 bit di entropia o più, il punto in cui la forza bruta smette di essere una strategia. Sono 32 caratteri hex, 22 caratteri base64url, o 43 caratteri base64url se vuoi 256 bit. Per un valore che solo il software maneggia, l’opzione più lunga non costa nulla.
È più sicuro che generare un segreto con Math.random?
Sì, e la differenza non è di grado. Math.random è un generatore pseudocasuale con uno stato piccolo che i motori attuali permettono di ricavare da una breve serie di uscite, dopodiché ogni valore che produrrà è noto. Questo strumento usa crypto.getRandomValues, il CSPRNG della piattaforma, la stessa fonte a cui attinge openssl rand.
Perché non mostrate un unico «tempo per craccarlo»?
Perché quel numero non esiste. Lo stesso segreto è irraggiungibile dietro un accesso che limita la frequenza e cade in fretta dietro un hash veloce trapelato: undici ordini di grandezza di distanza. Una cifra sola deve scegliere un’ipotesi e poi nasconderla, e chi legge ricorda il numero, non l’ipotesi. Tre velocità con un nome mettono l’ipotesi dove si vede.
Le passphrase sono più deboli di una stringa casuale?
No: la forza dipende solo da quante parole si estraggono da un elenco di quale dimensione, e sono mostrate entrambe. Sei parole dall’elenco lungo della EFF sono circa 77 bit, più di una password casuale di dieci caratteri. Ciò che indebolisce una passphrase è sceglierne le parole da sé, cosa che qui non avviene.
Conviene escludere i caratteri somiglianti?
Se una persona leggerà il segreto a schermo per digitarlo altrove, sì: il costo è piccolo e un token letto male diventa una richiesta di assistenza. Se lo maneggia solo il software, non c’è ragione. Togliere 0, O, I e l porta l’alfabeto da 62 a 58 caratteri, che è esattamente l’alfabeto base58, e costa circa un carattere di lunghezza ogni dodici.
Mettere le maiuscole rende una passphrase più forte?
No. È la stessa modifica applicata ogni volta, quindi non aggiunge una sola possibilità allo spazio delle passphrase. Il numero di entropia resta fermo quando lo attivi, ed è il comportamento corretto. L’opzione c’è perché alcuni campi password insistono su una maiuscola.
Qualcosa di ciò che genero viene inviato a un server?
No. La generazione avviene interamente nel tuo browser con il generatore di casualità della piattaforma; nulla viene caricato o registrato, e funziona senza connessione di rete. I token non sono conservati da nessuna parte: ricaricare la pagina ne produce di nuovi e i vecchi spariscono.