Cos'è un generatore di numeri casuali?
Un generatore di numeri casuali (RNG) è un sistema che produce numeri casuali o pseudocasuali. La reale possibilità di prevedere il numero successivo dipende dal tipo di generatore. Alcuni generatori si basano su un processo fisico, altri calcolano i numeri tramite un algoritmo, e alcuni algoritmi sono progettati in modo che nemmeno chi ha visto i loro valori generati possa prevedere cosa verrà dopo. Sembrare casuale ed essere imprevedibile sono due proprietà distinte, e la maggior parte di questo articolo è dedicata a questa differenza.
Generatori hardware di numeri casuali
Un generatore hardware di numeri casuali (HRNG), noto anche come generatore di numeri realmente casuali (TRNG), ricava i numeri da un processo fisico. Gli esempi più antichi funzionano sotto i nostri occhi: una moneta lanciata, un dado che rotola, la ruota di una roulette. La meccanica descrive ciascuno di essi in modo completo, eppure una roulette ben realizzata rimane imprevedibile nella pratica, perché minime variazioni nel modo in cui inizia ogni giro si trasformano in esiti completamente diversi.
I moderni generatori hardware misurano invece fenomeni microscopici: il rumore termico e il rumore shot nei circuiti elettronici, i disturbi atmosferici, gli effetti quantistici. Si tratta di ottime fonti di entropia — ovvero imprevedibilità misurabile — ma una sorgente fisica non è perfetta per natura: può presentare distorsioni, può subire derive (drift) e può guastarsi. Di conseguenza, la sua qualità deve essere valutata e monitorata, e i dati prodotti devono essere ulteriormente elaborati ove necessario, come descritto da standard quali NIST SP 800-90B. Le sorgenti hardware vengono impiegate dove le garanzie contano di più — soprattutto nella crittografia, dove forniscono il materiale iniziale imprevedibile per le chiavi alla base di protocolli come Transport Layer Security (TLS).
Generatori di numeri pseudocasuali
L'alternativa a un dispositivo fisico è un algoritmo. Un generatore di numeri pseudocasuali (PRNG) produce una sequenza che appare casuale ma è completamente determinata da un valore iniziale chiamato seme (seed). Fornendo lo stesso seme allo stesso algoritmo si otterrà la medesima sequenza ogni volta. Questo rappresenta un punto debole quando il risultato deve essere imprevedibile e il seme o lo stato interno possono essere indovinati o ricostruiti, ma è un punto di forza quando il risultato deve essere riproducibile — ad esempio per eseguire nuovamente una simulazione o un test con gli stessi esatti valori. I PRNG sono inoltre veloci, economici e facili da implementare, motivo per cui la maggior parte del software fa affidamento su di essi. Tra gli algoritmi più noti figurano il generatore congruenziale lineare (LCG), i generatori xorshift e il Mersenne Twister.
Mersenne Twister
Il Mersenne Twister, pubblicato nel 1997 da Makoto Matsumoto e Takuji Nishimura, è uno dei generatori di numeri pseudocasuali più diffusi ed è il generatore predefinito in molti linguaggi di programmazione. Il suo nome deriva dal suo periodo — la lunghezza della sequenza prima che inizi a ripetersi — che nella variante standard, MT19937, corrisponde al numero primo di Mersenne 219937 − 1. Supera la maggior parte dei test statistici di casualità ed è particolarmente adatto alle simulazioni. Tuttavia, non è stato progettato per proteggere segreti: partendo da 624 valori consecutivi a 32 bit, chiunque può ricostruire il suo stato interno e prevedere ogni valore successivo; pertanto non deve mai essere utilizzato per chiavi, password o qualunque altro elemento che debba rimanere imprevedibile.
Generatori crittograficamente sicuri ed entropia
Molte applicazioni richiedono entrambe le caratteristiche contemporaneamente: la velocità di un algoritmo e l'imprevedibilità di una sorgente fisica. La risposta è un generatore di numeri pseudocasuali crittograficamente sicuro (CSPRNG). Si tratta pur sempre di un PRNG, ma progettato in modo che l'osservazione di una parte dei suoi valori non offra alcun modo pratico per prevedere il resto, ed è inizializzato, e periodicamente reinizializzato, a partire da una fonte di vera entropia. Un seme proveniente da una sorgente fisica non rende sicuro un normale PRNG; l'algoritmo stesso deve essere strutturato per questo scopo. Una sorgente fisica come il rumore termico o i tempi degli eventi hardware fornisce una piccola quantità di vera casualità, e il CSPRNG ne ricava una lunga sequenza di valori, a una velocità molto superiore. Questa combinazione è ciò che un sistema operativo mette a disposizione dei programmi in esecuzione, ed è ciò che oggi si intende comunemente con "generatore di numeri casuali". Produce chiavi crittografiche, token di sessione e password.
Numeri casuali nel browser
JavaScript offre a una pagina web due metodi integrati per ottenere valori casuali, appartenenti a classi diverse. Math.random() è un normale PRNG: lo standard del linguaggio lascia la scelta dell'algoritmo a ciascun browser e non garantisce alcuna sicurezza — va bene per un'animazione, ma non è adatto a un'estrazione che qualcuno potrebbe contestare. L'altro metodo è la Web Crypto API. La sua funzione crypto.getRandomValues() restituisce valori casuali crittograficamente sicuri, prodotti da un CSPRNG alimentato con l'entropia del sistema operativo.
Il nostro generatore di numeri casuali online utilizza la Web Crypto API per ogni estrazione, e i numeri vengono generati direttamente nel tuo browser anziché su un server. La stessa sorgente alimenta gli altri generatori di questo sito, che tu voglia lanciare dei dadi, lanciare una moneta o generare una password.
Dai bit casuali a un numero nel tuo intervallo
Un generatore crittograficamente sicuro rappresenta solo metà del lavoro per un'estrazione equa. Fornisce bit grezzi, e il programma deve poi trasformarli in un numero compreso nell'intervallo che ti serve — ed è proprio qui che può insinuarsi una distorsione. Supponi che la sorgente fornisca i valori da 0 a 9 con pari probabilità e che tu abbia bisogno di un numero da 0 a 5. Prendere il resto della divisione per 6 può sembrare naturale, ma in questo modo 0, 1, 2 e 3 possono presentarsi ciascuno in due modi diversi, mentre 4 e 5 solo in uno. Di conseguenza, ciascuno dei numeri da 0 a 3 avrà il 20% di probabilità, mentre 4 e 5 solo il 10% ciascuno. Un modo per eliminare questa distorsione (modulo bias) consiste nello scartare i valori in eccesso ed estrarre nuovamente; le guide sui generatori di numeri casuali approfondiscono questo aspetto nel dettaglio.
Altre due cose sorprendono spesso gli utenti. Le ripetizioni sono normali: quando si estrae un numero intero da 1 a 10 in modo indipendente e con uguale probabilità per ogni numero, quello appena estratto ha esattamente la stessa probabilità di 1 su 10 di uscire nuovamente rispetto a qualunque altro. Un'estrazione senza ripetizioni è un tipo diverso di estrazione, non un'estrazione più casuale. Inoltre, un generatore equo da solo non rende equa l'intera procedura: l'elenco dei partecipanti e il numero di tentativi contano altrettanto, come spiegato nella nostra guida su come scegliere un vincitore casuale di un contest.