Perché il bug dei numeri casuali in Javascript non è un bug
In questi giorni (14 gennaio 2016), si fa un gran parlare del presunto “bug” trovato da Sebastiano Vigna nell’algoritmo di generazione dei numeri casuali in javascript, alla base della classica funzione Math.random(); e risolto modificando l’algoritmo alla base con lo xorshift128+.
Repubblica scrive:
Il difetto riguarda come detto la funzionalità necessaria ad esempio a identificare le transazioni negli acquisti online o per introdurre casualità nei videogiochi (basti pensare all’estrazione dei biglietti di una lotteria o alla distribuzione delle carte nel poker online).
Per concludere con un:
La falla più grave è stata scoperta da una start-up che si occupa di scommesse online. “Usando JavaScript per gestire il sito, è emerso che l’algoritmo estraeva numeri simili più spesso di quanto ci si poteva attendere, rischiando di identificare due scommesse diverse con la stessa sequenza di numeri”
Ora, senza nulla togliere a Sebastiano Vigna, che probabilmente non ha nulla a che fare con gli articoli sensazionalistici, vanno fatte diverse precisazioni, in particolar modo per i non addetti ai lavori.
La generazione dei numeri casuali tramite computer è un argomento complesso e di non facilissima comprensione. I generatori casuali oggi presenti sono diversi e suddivisi in diverse categorie, dai banali PRNG (pseudo-random number generator), CSPRNG (cryptographically secure pseudo-random number generator), e così via, fino ai generatori di numeri davvero casuali (TRNG, true random number generator).
Senza entrare troppo nello specifico, i PRNG sono i più “banali”, e utilizzati in tutti i casi in cui la reale casualità non è questione di vita o di morte. Utilizzano un seme da cui estrarre una sequenza attraverso diversi metodi (uno di questi è lo xorshift128+). I CSPRNG utilizzano sistemi avanzati e più lenti, utilizzati perlopiù in ambito crittografico per la generazione di coppie di chiavi pubbliche/private. Questi ultimi accumulano maggiore entropia rispetto ai primi, utilizzando qualsiasi variabile a disposizione (ad esempio: i movimenti del mouse dell’utente, gli ultimi settori scritti su disco, il numero di pacchetti inviati nella rete, e via dicendo).
Infine, i TRNG, i generatori di numeri casuali veri, hanno bisogno di dispositivi fisici, hardware, che tramite diversi metodi fisici provvedono entropia al generatore. Questi ultimi sono quelli che, per legge, è necessario usare in contesti delicati, uno tra questi, ad esempio, le scommesse online, i giochi a premi, le estrazioni della lotteria.
Tornando all’articolo: si parla di un bug in javascript, linguaggio utilizzato client-side, ovvero sul browser dell’utente. (n.d.: negli ultimi anni si sta diffondendo l’utilizzo di node.js, framework per l’utilizzo server-side del javascript; ma questo è un altro discorso), a che pro fare il paragone con acquisti online o estrazione di biglietti della lotteria?
Un programmatore che utilizza il Math.random() di javascript per operazioni così delicate non è un programmatore, e ancor meno chi effettua le operazioni di generazione client-side.
Dire “ci siamo accorti che dopo un po’ il Math.random() rigenera la stessa sequenza di numeri” è un po’ come scoprire l’acqua calda: dato un seme iniziale al generatore, la sequenza sarà sempre identica.
E non vorrei essere nei panni di quella start-up che, a quanto pare, ha davvero basato il suo algoritmo sul Math.random() di javascript.
Una piccola curiosità: nei videogiochi (quelli di puro intrattenimento, non lotterie, scommesse, o casinò online), nella stragrande maggioranza dei casi, le probabilità sono pilotate e volutamente simulate. Ad esempio, un lancio di una moneta in un videogioco, che può dare testa o croce, raramente darà una serie continua di “testa” o di “croce”, ma le alternerà periodicamente in modo da dare l’illusione al giocatore che la probabilità sia realistica.
Naturalmente, chiunque abbia seguito un corso di probabilità e statistica sa che è ugualmente probabile che, nella realtà, si abbiano una continua serie di soli “testa” o solo “croce”. Provate a pensare alla furbata del raddoppio giocando sul nero o sul rosso alla roulette; e vedrete perché è così irrealistica.
[Nota: se vi interessa, qui trovate i dettagli dello xorshift128+, realizzato dall’Università Statale di Milano, di cui Vigna è uno dei professori]
Quindi non ho capito se sia veramente random o meno
No. Math.random() è una funzione che ritorna dei numeri che si possono prevedere, dato il seme, che di solito è il tempo corrente in millisecondi.