Come generare un byte casuale altamente imprevedibile

1
void
 vncRandomBytes(unsigned char *bytes)
{
int i;
unsigned int seed = (unsigned int) time(0) + getpid() + rand();

srand(seed);
for (i = 0; i < CHALLENGESIZE; i++) {
    bytes[i] = (unsigned char)(rand() & 255);    
}
}

Può sopra il codice considerare un generatore di stringa casuale sicuro?

    
posta user236501 18.01.2013 - 18:25
fonte

2 risposte

7

No, scusa, il tuo generatore è terribilmente cattivo. Lo semini con valori che non hanno molta entropia (il PID si adatta a 16 bit ...) o sono altamente ipotizzabili (il "tempo corrente" non è esattamente un valore segreto, chiunque può conoscerlo con notevole precisione). E il generatore che si nasconde sotto rand() è noto per essere irrinunciabile (dipende dal sistema operativo attuale, ma molti sistemi usano un generatore di congruenza lineare che può essere facilmente invertito).

Otterrai qualcosa che sembra vagamente casuale a prima vista, ma non resisterà ai tentativi riusciti di scoppiarlo, cioè a prevedere l'uscita futura del generatore. Resistere ai tentativi di cracking da parte di aggressori intelligenti è tutto ciò che riguarda la sicurezza. Il tuo generatore potrebbe essere appropriato per alcuni usi non correlati alla sicurezza, sebbene (anche se rand() è noto per essere piuttosto negativo in quelli).

Per la generazione corretta del numero casuale, è necessario:

  1. un seme iniziale con sufficiente entropia;
  2. a PRNG crittograficamente sicuro che espanderà quel seme in un lungo flusso di byte che sarà indistinguibile dalla casualità (anche agli occhi di un individuo intelligente e potente con grandi computer intenzionati a predire il prossimo byte casuale.

Il seme iniziale deve provenire da alcuni eventi hardware (casualità "fisica"), perché il software è, fino al livello transistor, deterministico. Il sistema operativo è in una posizione ideale per raccogliere eventi fisici (è il suo lavoro, dopo tutto). Pertanto, utilizzare il sistema operativo. Questo significa:

  • Su sistemi di tipo Unix (come Linux, FreeBSD, Solaris, MacOS X ...), usa /dev/urandom ( non /dev/random ; vedi questa risposta per i dettagli).
  • In Windows (Win32), chiama CryptGenRandom() .
  • Su Java, usa java.security.SecureRandom .
  • Su .NET, usa System.Security.Cryptography.RNGCryptoServiceProvider .
risposta data 18.01.2013 - 19:14
fonte
3

Sfortunatamente questo non genererà materiale ad alta entropia. Praticamente qualsiasi tipo di generazione pseudo-casuale nel software (come rand() ) non sarà adatto per generare byte casuali di buona qualità.

La maggior parte dei sistemi operativi ha una sorta di flusso massimo di entropia, supportato da hardware che genera entropia. Ad esempio /dev/random su macchine basate su unix. La lettura da quel flusso è la più vicina alla probabilità di ottenere 1 bit di entropia per bit di dati.

Modifica: i miei stimati colleghi hanno sottolineato che l'utilizzo di /dev/urandom è accettabile per la generazione di byte ad alta entropia. Non blocca il modo in cui /dev/random , quindi esegue infinitamente meglio se è necessario generare un numero elevato di byte.

    
risposta data 18.01.2013 - 18:33
fonte

Leggi altre domande sui tag