Generalmente dipende dall'implementazione. Per la maggior parte, guarderai Generatori di Congruenze lineari o Registri a scorrimento feedback lineare .
Un problema comune con questi tipi di generatori è che il loro periodo è generalmente piuttosto breve e che la loro forma matematica implica una generazione deterministica. In quanto tale, puoi (generalmente) romperle in poche centinaia di chiamate o meno. I risultati sequenziali rendono più semplice l'interruzione dell'algoritmo, dal momento che è possibile creare correlazioni più forti in questo modo, ma non sono necessari.
Il più grande difetto con i generatori "nuovi" è che il seme non è sufficientemente grande. Ad esempio, se si dispone di un generatore con un seme a 32 bit e si conoscono i primi 20 valori del generatore, è banale la forza bruta. Basta generare una sequenza per ogni seme da 0 a 2 ^ 32 e confrontarlo. Puoi utilizzare l'ottimizzazione anticipata per ridurre in modo massivo il costo computazionale di questo.
Pseudo codice:
// the known values from the generator
byte[] knownValues = { 9, 55, 201, 50, 41, 111, 67, 44, 122, 66 };
for(seed = 0 to 2^32)
{
srand(seed);
bool found = true;
for(n = 0 to len(knownValues))
{
if(rand() != knownValues[n])
{
found = false;
break;
}
}
if(found == true)
{
print "Found potential seed: " + seed + "\n";
}
}
Con un RNG abbastanza veloce e alcuni hardware decenti, questo diventa sicuramente un attacco plausibile.
Ti consiglio di leggere quanto segue per una spiegazione esauriente: