Come gestire un generatore SecureRandom lento?


165

Se si desidera un numero casuale crittograficamente forte in Java, si utilizza SecureRandom. Sfortunatamente, SecureRandompuò essere molto lento. Se lo utilizza /dev/randomsu Linux, può bloccare l'attesa per la creazione di entropia sufficiente. Come evitare la penalità per le prestazioni?

Qualcuno ha usato Uncommon Maths come soluzione a questo problema?

Qualcuno può confermare che questo problema di prestazioni è stato risolto in JDK 6?


Sembra che questo sia legato alla lentezza di SecureRandom.generateSeed () . C'è un difetto respinto che spiega la lentezza e una soluzione alternativa: JDK-6521844: SecureRandom si blocca su sistemi Linux
AlikElzin-kilaka

Dai un'occhiata a / dev / urandom (non / dev / random). Prendi in considerazione l'idea di ottenere un seed del generatore di numeri casuali da urandom in caso di problemi di blocco.
jcalfee314,

Risposte:


79

Se vuoi veri dati casuali, sfortunatamente devi aspettarli. Ciò include il seme per un SecureRandomPRNG. La matematica non comune non può raccogliere dati casuali reali più rapidamente di SecureRandom, sebbene possa connettersi a Internet per scaricare i dati seed da un determinato sito Web. La mia ipotesi è che è improbabile che questo sia più veloce di /dev/randomdove sia disponibile.

Se vuoi un PRNG, fai qualcosa del genere:

SecureRandom.getInstance("SHA1PRNG");

Le stringhe supportate dipendono dal SecureRandomprovider SPI, ma è possibile enumerarle utilizzando Security.getProviders()e Provider.getService().

Sun ama SHA1PRNG, quindi è ampiamente disponibile. Non è particolarmente veloce come vanno i PRNG, ma i PRNG scricchiolano semplicemente i numeri, non bloccano la misurazione fisica dell'entropia.

L'eccezione è che se non si chiama setSeed()prima di ottenere i dati, il PRNG eseguirà il seeding stesso alla prima chiamata next()o nextBytes(). Di solito lo farà usando una quantità abbastanza piccola di dati casuali reali dal sistema. Questa chiamata potrebbe essere bloccata, ma renderà la tua fonte di numeri casuali molto più sicura rispetto a qualsiasi variante di "hash l'ora corrente insieme al PID, aggiungi 27 e spera per il meglio". Se tutto ciò di cui hai bisogno sono numeri casuali per un gioco, o se vuoi che lo stream sia ripetibile in futuro usando lo stesso seme a scopo di test, un seme insicuro è comunque utile.


Uncommons Maths scarica solo i dati da Internet per il seeding, non restituisce tali dati casuali durante la generazione di numeri casuali.
Dan Dyer,

Lo stesso con SecureRandom - / dev / urandom è solo per il seeding.
AviD,

Sì. Quando l'interrogante dice "se vuoi un numero casuale usi SecureRandom - questo può essere lento", ho pensato che forse stava usando getSeed per tutto e vuotando il suo pool di entropia. La soluzione non è ottenere JDK 6, è usare SecureRandom come previsto ;-)
Steve Jessop,

@Dan Dyer - Ho corretto il mio commento su Uncommon Maths. Ho dato un'occhiata alla tua pagina, quindi sapevo che per "numeri casuali" intendevo "per il suo seme" piuttosto che "tornare all'utente". Ma hai ragione, non è quello che ho detto ...
Steve Jessop,

"è ampiamente disponibile". Non è incluso in tutti i JDK conformi? È nella lista dei nomi degli standard di sicurezza Java ... ( docs.oracle.com/javase/8/docs/technotes/guides/security/… )
Sean Reilly,

176

Dovresti essere in grado di selezionare il più veloce ma leggermente meno sicuro / dev / urandom su Linux usando:

-Djava.security.egd=file:/dev/urandom

Tuttavia, questo non funziona con Java 5 e versioni successive ( Java Bug 6202721 ). La soluzione suggerita è di usare:

-Djava.security.egd=file:/dev/./urandom

(nota il extra /./)


24
Si noti che il rapporto Bug Java dice "Not a defect". In altre parole, anche se il valore predefinito è /dev/urandom, Sun lo considera come una stringa magica e lo utilizza /dev/randomcomunque, quindi è necessario falsificarlo. Quando un file:URL non è un file:URL? Ogni volta che Sun decide che non lo è :-(
Jim Garrison,

6
Avendo appena trascorso un sacco di tempo a indagare su questo, sembra che l'impostazione normale, anche con file:/dev/urandomset in -Djava.security.egdo in securerandom.sourcenel file java.security, /dev/random/venga comunque letta ogni volta SecureRandom.getSeed()(o setSeed()viene chiamata). La soluzione con i file:/dev/./urandomrisultati non risulta affatto leggibile /dev/random(confermata da strace)
matt b

7
/dev/urandomnon è meno sicuro di /dev/randomquando implementato con un CSPRNG moderno: en.wikipedia.org/wiki//dev/random#FreeBSD
lapo,

Penso che il timore principale /dev/urandom/sia quello che succede se lo usi per generare segreti sul nuovo hardware, che potrebbe essere in uno stato abbastanza prevedibile. /dev/urandom/non bloccherà l'entropia anche se questo è un caso in cui dovresti. La situazione è ancora peggiore se il segreto è persistente, come se la prima cosa che il tuo dispositivo fa al primo avvio è generare una coppia di chiavi pubblica-privata. Al di fuori di quelle situazioni spaventose, un bene /dev/urandomè comunque meglio che utilizzare gli SecureRandomalgoritmi comuni .
Steve Jessop,

1
Quale è corretto ? -Djava.security.egd = file: / dev /./ urandom o file: /// dev / urandom @mattb
Aarish Ramesh

35

Su Linux, l'implementazione predefinita per SecureRandomè NativePRNG(codice sorgente qui ), che tende ad essere molto lento. Su Windows, il valore predefinito è SHA1PRNG, che come altri hanno sottolineato, è possibile utilizzare anche su Linux se lo si specifica esplicitamente.

NativePRNGdifferisce da SHA1PRNGe Uncommons AESCounterRNG di Maths in quanto riceve continuamente entropia dal sistema operativo (leggendo da /dev/urandom). Gli altri PRNG non acquisiscono alcuna entropia aggiuntiva dopo la semina.

AESCounterRNG è circa 10 volte più veloce di SHA1PRNG, mentre IIRC è esso stesso due o tre volte più veloce di NativePRNG.

Se hai bisogno di un PRNG più veloce che acquisisca entropia dopo l'inizializzazione, vedi se riesci a trovare un'implementazione Java di Fortuna . Il PRNG di base di un'implementazione di Fortuna è identico a quello utilizzato da AESCounterRNG, ma esiste anche un sofisticato sistema di pooling di entropia e reseeding automatico.


Questo link non funziona. uncommons-maths.dev.java.net/nonav/api/org/uncommons/maths/… . C'è un posto dove posso vederlo?
UVM,

@Unni Ho appena aggiornato il link. Si noti che le dichiarazioni di prestazione che ho formulato in questa risposta potrebbero non essere più valide. Penso che le cose potrebbero essere andate meglio nelle ultime versioni di Java e che ci possano essere differenze nelle prestazioni tra le piattaforme (cioè Windows vs. Liux).
Dan Dyer,

Stavo solo eseguendo un esempio di SecureRandom con un MessageDigest e ho creato un codice esadecimale. L'intera operazione nel mio PC Windows 7 ha richiesto 33 millisecondi. È un problema. Ho usato SHA1PRNG.SecureRandom prng = SecureRandom.getInstance ("SHA1PRNG"); String randomNum = new Integer (prng.nextInt ()) .toString (); MessageDigest sha = MessageDigest.getInstance ("SHA-1"); result = sha.digest (randomNum.getBytes ()); str = hexEncode (risultato);
UVM,

24

Molte distro Linux (principalmente basate su Debian) configurano OpenJDK per l'uso /dev/randomper l'entropia.

/dev/random è per definizione lento (e può persino bloccare).

Da qui hai due opzioni su come sbloccarlo:

  1. Migliora l'entropia, o
  2. Ridurre i requisiti di casualità.

Opzione 1, migliorare l'entropia

Per ottenere più entropia /dev/random, prova il demone affamato . È un demone che raccoglie continuamente l'entropia di HAVEGE e funziona anche in un ambiente virtualizzato perché non richiede alcun hardware speciale, solo la CPU stessa e un clock.

Su Ubuntu / Debian:

apt-get install haveged
update-rc.d haveged defaults
service haveged start

Su RHEL / CentOS:

yum install haveged
systemctl enable haveged
systemctl start haveged

Opzione 2. Ridurre i requisiti di casualità

Se per qualche ragione la soluzione sopra non aiuta o non ti interessa la casualità crittograficamente forte, puoi /dev/urandominvece passare a , che è garantito per non bloccare.

Per farlo a livello globale, modifica il file jre/lib/security/java.securitynell'installazione Java predefinita da utilizzare /dev/urandom(a causa di un altro bug deve essere specificato come /dev/./urandom).

Come questo:

#securerandom.source=file:/dev/random
securerandom.source=file:/dev/./urandom

Quindi non dovrai mai specificarlo sulla riga di comando.


Nota: se si esegue la crittografia, è necessaria una buona entropia. Caso in questione: il problema del PRNG Android ha ridotto la sicurezza dei portafogli Bitcoin.


La tua risposta è stata annullata, ma " /dev/randomè per definizione lento (e può persino bloccare)" è sbagliato; dipende interamente dalla configurazione del sistema. Le macchine più recenti possono ad esempio avere un RNG veloce nella CPU che può essere utilizzato e le macchine BSD generalmente hanno la stessa implementazione per /dev/randome /devl/urandom. Tuttavia, probabilmente non dovresti fare affidamento sul fatto di /dev/random essere veloce, necessariamente. Sulle macchine virtuali potresti voler installare il set di strumenti client sulla macchina virtuale client in modo che sia possibile utilizzare l'RNG del sistema operativo host.
Maarten Bodewes,

17

Ho avuto un problema simile con le chiamate al SecureRandomblocco per circa 25 secondi alla volta su un server Debian senza testa. Ho installato il havegeddemone per assicurarmi che /dev/randomsia mantenuto pieno , su server senza testa è necessario qualcosa del genere per generare l'entropia richiesta. Le mie chiamate a SecureRandomora forse impiegano millisecondi.


4
apt-get install haveged quindi update-rc.d hanno impostazioni predefinite
Rod Lima,

11

Se vuoi una casualità veramente "crittograficamente forte", allora hai bisogno di una forte fonte di entropia. /dev/randomè lento perché deve attendere che gli eventi di sistema raccolgano entropia (letture del disco, pacchetti di rete, spostamento del mouse, pressione dei tasti, ecc.).

Una soluzione più veloce è un generatore di numeri casuali hardware. Potresti già averne uno integrato nella scheda madre; consulta la documentazione hw_random per istruzioni su come capire se ce l'hai e su come usarla. Il pacchetto rng-tools include un demone che alimenterà l'entropia generata dall'hardware /dev/random.

Se un HRNG non è disponibile sul tuo sistema e sei disposto a sacrificare la forza dell'entropia per le prestazioni, vorrai seminare un buon PRNG con i dati /dev/randome lasciare che il PRNG faccia il grosso del lavoro. Esistono diversi PRNG approvati dal NIST elencati in SP800-90 che sono facili da implementare.


Buon punto, ma il mio codice fa parte di un'applicazione commerciale. Non ho alcun controllo sull'ambiente server. Penso che i server di destinazione siano sempre senza mouse e tastiera e si basino interamente sull'I / O del disco e della rete per l'entropia, che è probabilmente il problema principale.
David G,

3
Ho scoperto che / dev / random dipendeva da eventi di sistema, quindi come soluzione temporanea, ho appena spostato il mouse avanti e indietro mentre il test era in esecuzione ....
David K

Quell'hub 82802 per il chipset i820 era dolorosamente lento (RIP). Sono sorpreso che tu possa ricavarne qualcosa di utile. Penso di aver trascorso più tempo a bloccarlo piuttosto che a collezionare ottetti.
jww,

6

Usando Java 8, ho scoperto che sulla chiamata Linux SecureRandom.getInstanceStrong()mi avrebbe dato l' NativePRNGBlockingalgoritmo. Questo spesso si bloccherebbe per molti secondi per generare qualche byte di sale.

Sono passato invece a chiedere esplicitamente NativePRNGNonBlocking, e come previsto dal nome, non è più bloccato. Non ho idea di quali siano le implicazioni di sicurezza di questo. Presumibilmente la versione non bloccante non può garantire la quantità di entropia utilizzata.

Aggiornamento : Ok, ho trovato questa eccellente spiegazione .

In poche parole, per evitare il blocco, utilizzare new SecureRandom(). Questo utilizza /dev/urandom, che non blocca ed è sostanzialmente sicuro come /dev/random. Dal post: "L'unica volta che vorresti chiamare / dev / random è quando la macchina si avvia per la prima volta e l'entropia non si è ancora accumulata".

SecureRandom.getInstanceStrong() ti dà il RNG più forte in assoluto, ma è sicuro da usare solo in situazioni in cui un sacco di blocchi non ti influenzerà.


1
Consentirei solo getInstanceStrong()chiavi a lungo termine, come quelle per i certificati TLS. E anche allora preferirei utilizzare new SecureRandom()un generatore di coppie di chiavi conforme a FIPS o un generatore di numeri casuali. Quindi sì, questo fornisce una risposta, se /dev/urandom non si blocca: alla fine si basa ancora sull'entropia del sistema; ma è un ottimo consiglio in generale . In caso di /dev/urandomblocchi, potrebbe essere necessario correggere l'origine del problema anziché l'applicazione Java.
Maarten Bodewes,

5

C'è uno strumento (almeno su Ubuntu) che alimenterà la casualità artificiale nel tuo sistema. Il comando è semplicemente:

rngd -r /dev/urandom

e potresti aver bisogno di un sudo nella parte anteriore. Se non hai il pacchetto rng-tools, dovrai installarlo. Ci ho provato e sicuramente mi ha aiutato!

Fonte: matt vs world


2
Questo è un po 'pericoloso perché disabilita completamente la stima del livello di entropia del kernel Linux, a livello di sistema. Penso che a scopo di test (leggi: Jenkins che esegue la suite di test di un'app) usando /dev/./urandom vada bene, ma in produzione no.
mirabilos,

Questa è in realtà l'unica soluzione che ha funzionato per me. Ho avuto un problema di "non abbastanza entropia" durante la creazione di un progetto Android con Gradle su Jenkins CI e il passaggio di un parametro alla build non ha aiutato.
Slav

Ho dovuto combinare sudo rngd -r /dev/urandomcon sudo apt install rng-toolsin xenial
MrMesees

5

Ho affrontato lo stesso problema . Dopo aver cercato su Google con i giusti termini di ricerca, mi sono imbattuto in questo simpatico articolo su DigitalOcean .

hasged è una potenziale soluzione senza compromettere la sicurezza.

Sto semplicemente citando la parte pertinente dall'articolo qui.

Basato sul principio HAVEGE e precedentemente basato sulla libreria associata, hasged consente di generare casualità in base alle variazioni del tempo di esecuzione del codice su un processore. Poiché è quasi impossibile che un pezzo di codice impieghi lo stesso tempo esatto per essere eseguito, anche nello stesso ambiente sullo stesso hardware, i tempi di esecuzione di un singolo o più programmi dovrebbero essere adatti per eseguire il seeding di una fonte casuale. L'implementazione congedo semina l'origine casuale del tuo sistema (di solito / dev / random) usando le differenze nel contatore di timestamp (TSC) del tuo processore dopo aver eseguito ripetutamente un ciclo

Come installare hagedato

Seguire i passaggi in questo articolo. https://www.digitalocean.com/community/tutorials/how-to-setup-additional-entropy-for-cloud-servers-using-haveged

L'ho pubblicato qui


5

Il problema a cui hai fatto riferimento /dev/randomnon è con l' SecureRandomalgoritmo, ma con la fonte di casualità che utilizza. I due sono ortogonali. Dovresti capire quale dei due ti sta rallentando.

La pagina Matematica non comune che hai collegato menziona esplicitamente che non stanno affrontando la fonte di casualità.

Puoi provare diversi provider JCE, come BouncyCastle, per vedere se la loro implementazione SecureRandomè più veloce.

Una breve ricerca rivela anche patch Linux che sostituiscono l'implementazione predefinita con Fortuna. Non ne so molto di più, ma siete invitati a indagare.

Dovrei anche menzionare che mentre è molto pericoloso usare un SecureRandomalgoritmo mal implementato e / o una fonte di casualità, è possibile distribuire il proprio provider JCE con un'implementazione personalizzata di SecureRandomSpi. Per ottenere la firma del tuo provider dovrai eseguire un processo con Sun, ma in realtà è piuttosto semplice; hanno solo bisogno che tu gli invii un modulo via fax in cui dichiari di essere a conoscenza delle restrizioni all'esportazione degli Stati Uniti sulle librerie crittografiche.


Quei diversi provider JCE sono utili solo se usano un'altra fonte di entropia, il che significa sostanzialmente che devono usare un hardware specifico, come un HSM. Altrimenti hanno altrettanto probabilità di subire rallentamenti, a seconda di quanta entropia estraggono dal sistema.
Maarten Bodewes,

3

Usa il random sicuro come fonte di inizializzazione per un algoritmo ricorrente; potresti usare un twister di Mersenne per il lavoro in serie invece di quello in UncommonMath, che è in circolazione da un po 'e si è dimostrato migliore di altri prng

http://en.wikipedia.org/wiki/Mersenne_twister

Assicurati di aggiornare di tanto in tanto il casuale sicuro utilizzato per l'inizializzazione, ad esempio potresti avere un casuale casuale generato per client, utilizzando un generatore pseudo casuale di mersenne twister per client, ottenendo un grado di randomizzazione abbastanza elevato


2
Questa risposta è sbagliata: il twister di Mersenne non è un generatore di numeri casuali sicuro. Sarebbe un buon algoritmo per Random, ma non per SecureRandom.
Maarten Bodewes,

3

Secondo la documentazione , i diversi algoritmi utilizzati da SecureRandom sono, in ordine di preferenza:

  • Sulla maggior parte dei sistemi * NIX
    1. NativePRNG
    2. SHA1PRNG
    3. NativePRNGBlocking
    4. NativePRNGNonBlocking
  • Su sistemi Windows
    1. SHA1PRNG
    2. Windows PRNG

Da quando hai chiesto di Linux, sto ignorando l'implementazione di Windows, e anche SunPKCS11 che è davvero disponibile solo su Solaris, a meno che tu non l'abbia installato tu stesso - e quindi non te lo chiederesti.

Secondo la stessa documentazione, sono utilizzati questi algoritmi

SHA1PRNG
Il seeding iniziale viene attualmente eseguito tramite una combinazione di attributi di sistema e il dispositivo di raccolta entropia java.security.

NativePRNG
nextBytes() utilizza gli /dev/urandom
generateSeed()usi/dev/random

NativePRNGBlocking
nextBytes() e generateSeed()use/dev/random

NativePRNGNonBlocking
nextBytes() e generateSeed()utilizzo/dev/urandom

Ciò significa che se lo usi SecureRandom random = new SecureRandom(), scende in tale elenco fino a quando non ne trova uno che funziona, che in genere sarà NativePRNG. Ciò significa che si semina da /dev/random(o lo utilizza se si genera esplicitamente un seme), quindi lo utilizza /dev/urandomper ottenere i byte, gli ints, il double, i booleani successivi, il what-have-yous.

Poiché /dev/randomsta bloccando (blocca fino a quando non ha abbastanza entropia nel pool di entropia), ciò può impedire le prestazioni.

Una soluzione a ciò sta usando qualcosa di simile all'haged per generare abbastanza entropia, un'altra /dev/urandominvece sta usando . Mentre potresti impostarlo per l'intero jvm, una soluzione migliore è farlo per questa specifica istanza di SecureRandom, usando SecureRandom random = SecureRandom.getInstance("NativePRNGNonBlocking"). Si noti che quel metodo può generare NoSuchAlgorithmException se NativePRNGNonBlocking, quindi prepararsi al fallback al valore predefinito.

SecureRandom random;
try {
    random = SecureRandom.getInstance("NativePRNGNonBlocking");
} catch (NoSuchAlgorithmException nsae) {
    random = new SecureRandom();
}

Si noti inoltre che su altri sistemi * nix, /dev/urandompotrebbe comportarsi diversamente .


È /dev/urandomabbastanza casuale?

La saggezza convenzionale vuole che /dev/randomsia abbastanza casuale. Tuttavia, alcune voci differiscono. In "Il modo giusto di utilizzare SecureRandom" e "Miti su / dev / urandom" , si sostiene che /dev/urandom/sia altrettanto buono.

Gli utenti dello stack Sicurezza delle informazioni concordano con questo . Fondamentalmente, se devi chiedere, /dev/urandomva bene per il tuo scopo.


2

Non ho affrontato questo problema da solo, ma ho generato un thread all'avvio del programma che tenta immediatamente di generare un seme, quindi muore. Il metodo chiamato per i random si unirà a quel thread se è attivo, quindi la prima chiamata si blocca solo se si verifica molto presto nell'esecuzione del programma.


È un trucco piuttosto estremo, ma potrebbe funzionare; non si dice che il PRNG usato non possa usare materiale di semina aggiuntivo che potrebbe comunque causare il blocco. L'uso di un diverso numero casuale che fornisce o fissa l'entropia nel sistema dovrebbe essere fortemente preferito. Dato che può almeno fornire una soluzione temporanea, ho comunque votato a favore della risposta.
Maarten Bodewes,

2

La mia esperienza è stata solo con l'inizializzazione lenta del PRNG, non con la generazione di dati casuali successivamente. Prova una strategia di inizializzazione più entusiasta. Dal momento che sono costosi da creare, trattalo come un singleton e riutilizzi la stessa istanza. Se c'è troppa contesa di thread per un'istanza, raggruppali o rendili thread-local.

Non scendere a compromessi sulla generazione di numeri casuali. Una debolezza compromette tutta la tua sicurezza.

Non vedo molti generatori COTS basati sul decadimento atomico, ma ci sono diversi piani là fuori per loro, se hai davvero bisogno di molti dati casuali. Un sito che ha sempre cose interessanti da guardare, tra cui HotBits, è il Fourmilab di John Walker.


1
Mi sono sempre chiesto questo, dal momento che i prodotti di decadimento della tau adronica quasi raggiungono l'ideale di una fonte randomizzata, non riesco proprio a liberarmi del mio desiderio di utilizzare questo invece di strumenti algoritmici. Ai fini dell'operazione, ho deciso molto tempo fa che un certo periodo di front-end è endemico per tutti gli strumenti sicuri. Se uno avrà bisogno di un randomizzatore, che può essere chiamato nel costruttore e ricorda solo di costruirne uno al momento del caricamento della pagina, è sepolto sotto lo swap-in avl e anche se schizzinoso come me non viene notato.
Nicholas Jordan,

I chipset Intel 8xx (e probabilmente molti altri) hanno un RNG hardware che utilizza il rumore termico, un effetto quantico davvero imprevedibile. I moduli di piattaforma affidabili possono contenere anche RNG hardware, ma sfortunatamente quello del mio laptop no.
Erickson,

Dipende dal RNG specifico se si semina una volta o se si ripristina dopo un po '. NIST specifica i PRNG che sono stati resed, ma molte implementazioni software no. Ristrutturare il codice attorno a un singleton è un'idea orribile, specialmente su implementazioni multithread; è meglio risolvere l'origine del problema: la lenta semina dovuta alla mancanza di entropia. Se si utilizza un singleton, utilizzarlo per fornire seed per altre implementazioni SecureRandom completamente deterministiche. Questo tipo di design probabilmente richiede una certa conoscenza.
Maarten Bodewes,

@MaartenBodewes Questi sono buoni punti. Se l'implementazione è una che blocca, in attesa dell'entropia del sistema, penso che trattarla come un singleton nella tua applicazione non sia un'idea orribile poiché la sorgente sottostante è effettivamente un singleton. Ma usare quell'istanza per seminare gli altri è un buon suggerimento, anche se complesso. Non ne sono sicuro, ma penso che il provider Sun (e quindi Oracle) SecureRandomsia cambiato un paio di volte negli ultimi 10 anni nella sua raccolta di entropia.
Erickson,

Sono molto sicuro che sia cambiato parecchie volte, tant'è che non proverò a mettere tutte le modifiche in questo commento :). È meno probabile che un rallentamento SecureRandomsia ancora un problema, ma la bassa entropia in un sistema sarà sempre un problema. L'uso di un singleton creerà un codice fortemente accoppiato, che è un modello anti-disegno. Dovrebbe quindi essere usato con estrema cura; preferibilmente dovresti invertire tutti i riferimenti nel codice per risolvere il problema.
Maarten Bodewes,

2

Sembra che dovresti essere più chiaro sui tuoi requisiti RNG. Il requisito di RNG crittografico più forte (a quanto ho capito) sarebbe che anche se si conosce l'algoritmo utilizzato per generarli e si conoscono tutti i numeri casuali generati in precedenza, non è possibile ottenere alcuna informazione utile su nessuno dei numeri casuali generati nel futuro, senza spendere una quantità impraticabile di potenza di calcolo.

Se non hai bisogno di questa piena garanzia di casualità, probabilmente ci sono compromessi prestazionali appropriati. Tenderei ad essere d'accordo con la risposta di Dan Dyer su AESCounterRNG di Uncommons-Maths o Fortuna (uno dei suoi autori è Bruce Schneier, un esperto di crittografia). Nemmeno io l'ho mai usato, ma le idee sembrano affidabili a prima vista.

Vorrei pensare che se si potesse generare periodicamente un seme casuale iniziale (ad esempio una volta al giorno o ora o qualsiasi altra cosa), è possibile utilizzare un cifrario a flusso veloce per generare numeri casuali da pezzi successive del flusso (se il cifrario a flusso utilizza XOR poi basta passare un flusso di valori null o afferrare direttamente i bit XOR). Di ECRYPT eStreamil progetto ha molte buone informazioni tra cui parametri di riferimento delle prestazioni. Ciò non manterrebbe l'entropia tra i punti nel tempo in cui lo si riempie, quindi se qualcuno conoscesse uno dei numeri casuali e l'algoritmo che hai usato, tecnicamente potrebbe essere possibile, con molta potenza di calcolo, rompere il codice di flusso e indovina il suo stato interno per essere in grado di prevedere i numeri casuali futuri. Ma dovresti decidere se quel rischio e le sue conseguenze sono sufficienti per giustificare il costo di mantenimento dell'entropia.

Modifica: ecco alcune note di corso crittografiche su RNG che ho trovato in rete che sembrano molto rilevanti per questo argomento.


1
"Fortuna (uno dei suoi autori è Bruce Schneier, un esperto di crittografia)" - e l'altro è Niels Ferguson, un esperto di crittografia :-)
Steve Jessop

2

Se il tuo hardware lo supporta, prova a utilizzare Java RdRand Utility di cui sono l'autore.

Si basa sulle RDRANDistruzioni di Intel ed è circa 10 volte più veloce di SecureRandome nessun problema di larghezza di banda per l'implementazione di grandi volumi.


Si noti che questa implementazione funziona solo su quelle CPU che forniscono le istruzioni (cioè quando rdrandè impostato il flag del processore). È necessario creare un'istanza esplicita tramite il RdRandRandom()costruttore; nessuno specifico Providerè stato implementato.


3
Potresti voler leggere people.umass.edu/gbecker/BeckerChes13.pdf ed essere sicuro di non usare mai solo i dati Intel RDRAND. Mischiatelo sempre con alcuni altri dati imprevedibili, come l'output di un codice di flusso aRC4 (seeded da / dev / urandom e con i primi pochi KiB di output eliminati per la loro distorsione nota).
mirabilos,

+1 mirabilos. Penso che RDRANDsia una buona fonte, ma è un po 'inaffidabile. Deve sicuramente essere un input di molti in un collezionista (senza offesa per David Johnston).
jww,

Ho votato, riparato il link e fornito alcune informazioni di base. Se non sei d'accordo, ripristina la modifica.
Maarten Bodewes,

1

Qualcos'altro da guardare è la proprietà securerandom.source nel file lib / security / java.security

Potrebbe esserci un vantaggio prestazionale nell'usare / dev / urandom piuttosto che / dev / random. Ricorda che se la qualità dei numeri casuali è importante, non scendere a compromessi che rompono la sicurezza.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.