Proverò a rispondere a una domanda semplificata: esiste un attacco fattibile su un vero CSPRNG (generatore di numeri casuali crittograficamente sicuro)? E poi, e se non fosse un CSPRNG perfetto?
caso 1)
Per semplificare le cose, supponiamo che non venga aggiunta entropia dopo l'impostazione di inizializzazione di un CSPRNG vero e deterministico. Inoltre, non assumere alcuna perdita di informazioni nell'inizializzazione.
Da wikipedia la definizione di CSPRNG è data come segue:
Every CSPRNG should satisfy the next-bit test. That is, given the first k bits of a random sequence, there is no polynomial-time
algorithm that can predict the (k+1)th bit with probability of success
non-negligibly better than 50%. Andrew Yao proved in 1982 that a
generator passing the next-bit test will pass all other
polynomial-time statistical tests for randomness.
Every CSPRNG should withstand "state compromise extensions". In the event that part or all of its state has been revealed (or guessed
correctly), it should be impossible to reconstruct the stream of
random numbers prior to the revelation. Additionally, if there is an
entropy input while running, it should be infeasible to use knowledge
of the input's state to predict future conditions of the CSPRNG state.
Ciò significa che anche se parte della sequenza di output casuale è trapelata, le parti della sequenza prima e dopo quella parte trapelata non possono essere determinate.
In questo caso sei completamente sicuro usando /dev/urandom
, anche se c'è una perdita dei dati della sequenza casuale e anche se non sono mai aggiunti dati casuali esterni alla sequenza dopo l'inizializzazione.
caso 2)
Supponiamo che il cosiddetto CSPRNG sia effettivamente rotto. Proprio per la vendita di argomentazioni supponiamo che data una perdita parziale della sequenza, sia le parti passate che quelle future della sequenza "abbastanza vicine" alla perdita siano severamente compromesse.
In un caso CSPRNG rotto, l'entropia aggiunta aggiungerà sicurezza al sistema. Se 256 veri bit di entropia separano la perdita e un numero casuale X usato per uno scopo critico, allora lo spazio di ricerca per un attacco su X viene ingrandito di 2 ^ 256 - ed è quindi totalmente sicuro.
Quindi il caso 2 è un rischio nelle seguenti 2 condizioni:
- C'è una perdita dello stato della sequenza casuale.
- Il PRNG non è un CSPRNG perfetto.
Ma garantire una sufficiente entropia può mitigare perfettamente il rischio.
Riguardo alla condizione (1): la possibilità di una perdita di dati. Alcune implementazioni Java forniscono accesso ai dati sottostanti / dev / random. Lo dice nella documentazione di Java.
È fantastico per la scelta di numeri casuali in Java, ma potrebbe essere utilizzato dal malware basato su Java per divulgare informazioni sulla sequenza casuale. Oltre a Java, ogni volta che crei una password casuale con il tuo software e la trasmetti a un sito web esterno, questo potrebbe far trapelare alcune informazioni sullo stato della sequenza casuale.
Riguardo alla condizione (2): mentre può essere possibile dimostrare che un particolare PRNG è non un CSPRNG, non è possibile dimostrare che un particolare PRNG è un CSPRNG. Devi solo sperare che il CSPRNG non sia stato smentito senza che tu te ne accorga. Ci sono anche sfumature di grigio: un attacco particolare apre solo una stretta finestra di vulnerabilità prima e dopo una perdita, e richiederebbe enormi risorse per sfruttarlo. Valutare il rischio di un attacco sconosciuto (a voi) con un numero concreto è difficile o impossibile, ma trattare il rischio come una variabile sconosciuta ed esaminare il costo della mitigazione rispetto alle conseguenze poiché il rischio varia è un esercizio significativo.
Nota: c'è una domanda per un laico: se il PRNG è deterministico, come può il prossimo bit non essere prevedibile se si verifica una perdita? La risposta è che sebbene l'algoritmo di sequenza casuale generale sia di per sé noto, la funzione utilizzata per la transizione da una coppia (valore, stato) alla successiva (valore, stato) coppia viene inizialmente scelta da una vasta famiglia di funzioni, ad esempio una di 2 ^ 256 di tali funzioni. Quindi è possibile utilizzare altri 256 bit per inizializzare la funzione scelta. (In realtà sono necessari solo 128 bit per inizializzare la sequenza /dev/random
).