Java SecureRandom non blocca? Come?

22

So per esperienza che sto leggendo da / dev / random blocks quando il pool entropy del kernel Linux finisce con l'entropia. Inoltre, ho visto molti articoli e post di blog che affermavano che quando si eseguiva su Linux, java.security.SecureRandom utilizza / dev / random come origine di entropia e quindi blocca quando il pool entropico del kernel si esaurisce nell'entropia.

Tuttavia, non sono in grado di produrre un esperimento che blocchi SecureRandom. Viceversa, sembra facile ottenere un semplice bash one-liner che legge da / dev / random per bloccare.

Ecco il codice java che sto usando per questi esperimenti:

import java.security.SecureRandom;

public class A {
    public static void main(String[] args) {
        SecureRandom sr = new SecureRandom();
        int out = 0;
        for (int i = 0; i < 1<<20 ; i++) {
            out ^= sr.nextInt();
        }
        System.out.println(out);
    }
}

Genera poco più di 1.000.000 di numeri casuali interi a 32 bit. Dovrebbe essere 2 ^ (20 + log2 (32)) = 2 ^ 25 bit o 2 ^ 22 (poco più di 4 milioni) byte di entropia, giusto? Tuttavia, non blocca mai. Finisce sempre in circa 1,2 secondi, indipendentemente dal fatto che io possa muovere il mouse o no.

Il one-liner bash che ho usato è:

head -c 100 /dev/random | xxd

Questo blocca facilmente. Fintanto che tengo la mia mano lontana dal mouse e dalla tastiera, rimarrà lì seduta senza fare nulla per diversi minuti. E sto solo chiedendo 100 byte di entropia.

Sicuramente mi manca qualcosa qui. Qualcuno potrebbe spiegare cosa sta succedendo?

Grazie!

    
posta user1483512 14.08.2013 - 20:46
fonte

5 risposte

37

Sia OpenJDK che Sun leggono da /dev/urandom , non /dev/random , almeno sulla macchina in cui sono stato testato (OpenJDK JRE 6b27 e Sun JRE 6.26 su Debian squeeze amd64). Per qualche motivo, aprono entrambi /dev/random ma non ne leggono mai. Quindi gli articoli sul blog che hai letto sono stati scambiati o applicati a una versione diversa dalla mia (e, apparentemente, dalla tua).

Puoi controllare se il tuo legge da /dev/random o /dev/urandom tracciandolo:

strace -o a.strace -f -e file java A

e cerca la parte rilevante della traccia:

21165 open("/dev/random", O_RDONLY)     = 6
…
21165 open("/dev/urandom", O_RDONLY)    = 7
…
21165 read(7, "2312Zs0564l44[wS6q@", 20) = 20
…

Non ti preoccupare, /dev/urandom va perfettamente bene per la crittografia.

    
risposta data 14.08.2013 - 21:02
fonte
9

Java SecureRandom fa usa / dev / random, ma solo brevemente.

In particolare lo utilizza solo durante la generazione di informazioni seed, chiamando esplicitamente SecureRandom.generateSeed() o prima chiamata a nextInt()

Quindi, per ripetere il tuo esempio di bash puoi fare quanto segue, e dovrebbe bloccare.

import java.security.SecureRandom;

public class A {
    public static void main(String[] args) {
        SecureRandom sr;
        int out = 0;
        for (int i = 0; i < 1<<20 ; i++) {
            sr = new SecureRandom();
            out ^= sr.nextInt();
        }
        System.out.println(out);
    }
}
    
risposta data 14.11.2014 - 07:06
fonte
3

$JAVA_HOME/lib/security/java.security : securerandom.source proprietà indica quale dispositivo utilizzare quando si utilizza SecureRandom . Il valore predefinito è /dev/urandom , il che significa che Java non verrà mai bloccato.

Per i nuovi arrivati all'argomento, /dev/urandom è la versione speciale di /dev/random , che userà l'entropia vera da /dev/random quando disponibile e quindi i dati pseudo casuali seminano l'entropia vera se fosse disponibile.

In ambienti headless, VM e Cloud, consiglio di seminare urandom da una fonte esterna, come link

    
risposta data 09.03.2014 - 20:01
fonte
3

Sul recente vintage Linux (ultimi 6 anni, diciamo) la differenza computazionale tra / dev / random (blocking) e / dev / urandom (non-blocking) è molto marginale; l'entropia grezza viene riciclata attraverso un generatore di numeri casuali ed entrambi i dispositivi utilizzano gli stessi bit. L'unica differenza è che / dev / random ha un limitatore di velocità che gli impedisce di funzionare troppo a lungo senza resuscitare. La stima del tasso di per sé è abbastanza discutibile.

Questo è spiegato in link che porta a casa il punto che / dev / urandom è sufficiente per seminare il tuo algoritmi crittografici per chiavi di sessione. Se non lo chiami troppo spesso, entrambi dovrebbero essere di qualità identica o quasi identica.

Ho visto il blocco tramite / dev / random durante l'esecuzione di un web crawler che doveva fare più di 1000 connessioni simultanee SSL (chiavi di sessione), e sì, siamo passati a / dev / urandom; per la generazione di grandi quantità di coppie di chiavi pubbliche / private di lunga durata (una situazione rara), un dispositivo entropico personalizzato è il migliore.

    
risposta data 30.09.2015 - 23:54
fonte
3

Non solo per mantenere vivo un vecchio thread ma alcune persone potrebbero aver perso una parte importante della lunga storia dietro a questo ... Si è trattato di un noto infame e persistente bug quando si utilizzava / dev / urandom dalle versioni 1.4 di Java alle versioni 1.7. Vedi i link qui sotto:

link

link

Per quello che so, questo è stato finalmente risolto in Java 8 come affermato da Oracle: link

SHA1PRNG and NativePRNG were fixed to properly respect the SecureRandom seed source properties in the java.security file. (The obscure workaround using file:///dev/urandom and file:/dev/./urandom is no longer required.)

    
risposta data 28.01.2016 - 18:20
fonte

Leggi altre domande sui tag