Wie gehe ich mit einem langsamen SecureRandom-Generator um?


165

Wenn Sie eine kryptografisch starke Zufallszahl in Java wünschen, verwenden Sie SecureRandom. SecureRandomKann leider sehr langsam sein. Wenn es /dev/randomunter Linux verwendet wird, kann es das Warten auf den Aufbau einer ausreichenden Entropie blockieren. Wie vermeidet man die Leistungsstrafe?

Hat jemand Uncommon Maths als Lösung für dieses Problem verwendet?

Kann jemand bestätigen, dass dieses Leistungsproblem in JDK 6 behoben wurde?


Es scheint, dass dies mit der Langsamkeit von SecureRandom.generateSeed () zusammenhängt . Es gibt einen zurückgewiesenen Fehler, der die Langsamkeit und eine Problemumgehung
AlikElzin-kilaka

Check out / dev / urandom (nicht / dev / random). Wenn es ein Blockierungsproblem gibt, sollten Sie nur einen Zufallszahlengenerator-Seed von urandom abrufen.
jcalfee314

Antworten:


79

Wenn Sie echte Zufallsdaten wollen, müssen Sie leider darauf warten. Dies beinhaltet den Startwert für ein SecureRandomPRNG. Gelegentlich kann Maths keine echten Zufallsdaten schneller erfassen als SecureRandom, obwohl es eine Verbindung zum Internet herstellen kann, um Startdaten von einer bestimmten Website herunterzuladen. Ich vermute, dass dies wahrscheinlich nicht schneller sein wird als /dev/randomdort, wo es verfügbar ist.

Wenn Sie ein PRNG möchten, gehen Sie wie folgt vor:

SecureRandom.getInstance("SHA1PRNG");

Welche Zeichenfolgen unterstützt werden, hängt vom SecureRandomSPI-Anbieter ab. Sie können sie jedoch mit Security.getProviders()und auflisten Provider.getService().

Sun liebt SHA1PRNG und ist daher weit verbreitet. Es ist nicht besonders schnell, wie PRNGs gehen, aber PRNGs werden nur Zahlen knacken und nicht für die physikalische Messung der Entropie blockieren.

Die Ausnahme ist, dass, wenn Sie nicht anrufen, setSeed()bevor Sie Daten erhalten, sich der PRNG beim ersten Aufruf von next()oder einmal selbst aussetzt nextBytes(). Dies geschieht normalerweise mit einer relativ kleinen Menge echter Zufallsdaten aus dem System. Dieser Aufruf kann blockieren, macht Ihre Zufallszahlenquelle jedoch weitaus sicherer als jede andere Variante von "Hash die aktuelle Zeit zusammen mit der PID, addiere 27 und hoffe auf das Beste". Wenn Sie jedoch nur Zufallszahlen für ein Spiel benötigen oder wenn Sie möchten, dass der Stream in Zukunft mit demselben Startwert zu Testzwecken wiederholt werden kann, ist ein unsicherer Startwert immer noch nützlich.


Uncommons Maths lädt nur Daten aus dem Internet zum Seeding herunter und gibt diese Zufallsdaten beim Generieren von Zufallszahlen nicht zurück.
Dan Dyer

Gleiches gilt für SecureRandom - das / dev / urandom dient nur zum Seeding.
AviD

Ja. Wenn der Fragesteller sagt "Wenn Sie eine Zufallszahl wollen, verwenden Sie SecureRandom - das kann langsam sein", dachte ich, dass er getSeed für alles verwendet und seinen Entropiepool leert. Das Update ist nicht, JDK 6 zu bekommen, sondern SecureRandom so zu verwenden, wie es beabsichtigt ist ;-)
Steve Jessop

@ Dan Dyer - Ich habe meinen Kommentar zu Uncommon Maths korrigiert. Ich habe mir Ihre Seite angesehen, also wusste ich, dass ich mit "Zufallszahlen" "für den Startwert" meinte und nicht "zum Benutzer zurückkehren". Aber Sie haben ganz recht, das habe ich nicht gesagt ...
Steve Jessop

"es ist weit verbreitet". Ist es nicht in jedem kompatiblen JDK enthalten? Es ist auf der Liste der Java-Sicherheitsstandardnamen ... ( docs.oracle.com/javase/8/docs/technotes/guides/security/… )
Sean Reilly

176

Sie sollten in der Lage sein, das schnellere, aber etwas weniger sichere / dev / urandom unter Linux auszuwählen, indem Sie:

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

Dies funktioniert jedoch nicht mit Java 5 und höher ( Java Bug 6202721 ). Die vorgeschlagene Problemumgehung lautet wie folgt:

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

(Beachten Sie das Extra /./)


24
Beachten Sie, dass im Java-Fehlerbericht "Kein Fehler" angegeben ist. Mit anderen Worten, obwohl die Standardeinstellung ist /dev/urandom, behandelt Sun dies als magische Zeichenfolge und verwendet sie /dev/randomtrotzdem, sodass Sie sie vortäuschen müssen. Wann ist eine file:URL keine file:URL? Wann immer Sun entscheidet, ist es nicht :-(
Jim Garrison

6
Nachdem Sie gerade einige Zeit damit verbracht haben, dies zu untersuchen, scheint es, dass die normale Einstellung, selbst wenn sie file:/dev/urandomin -Djava.security.egdoder securerandom.sourcein der Datei java.security festgelegt ist, /dev/random/immer noch gelesen wird, wenn sie aufgerufen wird SecureRandom.getSeed()(oder setSeed()aufgerufen wird). Die Problemumgehung file:/dev/./urandomführt dazu, dass überhaupt nicht gelesen wird /dev/random(bestätigt durch Strace)
matt b

7
/dev/urandomist nicht weniger sicher als /dev/randombei der Implementierung mit einem modernen CSPRNG: en.wikipedia.org/wiki//dev/random#FreeBSD
lapo

Ich denke, die Hauptangst /dev/urandom/ist, was passiert, wenn Sie damit sofort Geheimnisse für neue Hardware generieren, die sich in einem ziemlich vorhersehbaren Zustand befinden könnten. /dev/urandom/blockiert nicht für Entropie, obwohl dies ein Fall ist, in dem Sie sollten. Die Situation ist noch schlimmer, wenn das Geheimnis bestehen bleibt, beispielsweise wenn Ihr Gerät beim ersten Start als erstes ein öffentlich-privates Schlüsselpaar generiert. Außerhalb dieser beängstigenden Situationen ist ein Gut sowieso /dev/urandombesser als die Verwendung der üblichen SecureRandomAlgorithmen.
Steve Jessop

1
Welches ist korrekt ? -Djava.security.egd = Datei: / dev /./ urandom oder Datei: /// dev / urandom @mattb
Aarish Ramesh

35

Unter Linux SecureRandomlautet die Standardimplementierung für NativePRNG(Quellcode hier ), was in der Regel sehr langsam ist. Unter Windows ist der Standardwert SHA1PRNG, den Sie, wie bereits erwähnt, auch unter Linux verwenden können, wenn Sie ihn explizit angeben.

NativePRNGunterscheidet sich von SHA1PRNGund Uncommons Maths ' AESCounterRNG darin, dass es kontinuierlich Entropie vom Betriebssystem erhält (durch Lesen von /dev/urandom). Die anderen PRNGs erhalten nach dem Aussäen keine zusätzliche Entropie.

AESCounterRNG ist ungefähr 10x schneller als SHA1PRNG, IIRC selbst ist zwei- oder dreimal schneller als NativePRNG.

Wenn Sie ein schnelleres PRNG benötigen, das nach der Initialisierung Entropie erhält, prüfen Sie, ob Sie eine Java-Implementierung von Fortuna finden . Das Kern-PRNG einer Fortuna-Implementierung ist identisch mit dem von AESCounterRNG verwendeten, es gibt jedoch auch ein ausgeklügeltes System für Entropie-Pooling und automatische Neuaussaat.


Dieser Link funktioniert nicht. uncommons-maths.dev.java.net/nonav/api/org/uncommons/maths/… . Kann ich das irgendwo sehen?
UVM

@ Unni Habe gerade den Link aktualisiert. Bitte beachten Sie, dass die Leistungsansprüche, die ich in dieser Antwort geltend gemacht habe, möglicherweise nicht mehr gültig sind. Ich denke, die Dinge sind in den letzten Versionen von Java möglicherweise besser geworden, und es kann Unterschiede in der Leistung zwischen den Plattformen geben (z. B. Windows vs. Liux).
Dan Dyer

Ich habe nur ein Beispiel für SecureRandom mit einem MessageDigest ausgeführt und einen Hexencode erstellt. Der gesamte Vorgang in meinem Windows 7-PC dauerte 33 Millisekunden. Ist dies ein Problem. Ich habe SHA1PRNG.SecureRandom prng = SecureRandom.getInstance ("SHA1PRNG") verwendet. String randomNum = new Integer (prng.nextInt ()) .toString (); MessageDigest sha = MessageDigest.getInstance ("SHA-1"); result = sha.digest (randomNum.getBytes ()); str = hexEncode (Ergebnis);
UVM

24

Viele Linux-Distributionen (meistens auf Debian-Basis) konfigurieren OpenJDK /dev/randomfür die Entropie.

/dev/random ist per definitionem langsam (und kann sogar blockieren).

Von hier aus haben Sie zwei Möglichkeiten, wie Sie die Blockierung aufheben können:

  1. Entropie verbessern oder
  2. Reduzieren Sie die Zufallsanforderungen.

Option 1, Entropie verbessern

Probieren Sie/dev/random den Hgedged- Daemon aus, um mehr Entropie zu erhalten . Es ist ein Daemon, der kontinuierlich die HAVEGE-Entropie sammelt und auch in einer virtualisierten Umgebung funktioniert, da keine spezielle Hardware erforderlich ist, nur die CPU selbst und eine Uhr.

Unter Ubuntu / Debian:

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

Auf RHEL / CentOS:

yum install haveged
systemctl enable haveged
systemctl start haveged

Option 2. Reduzieren Sie die Zufallsanforderungen

Wenn die oben genannte Lösung aus irgendeinem Grund nicht hilft oder Sie sich nicht für kryptografisch starke Zufälligkeiten interessieren, können Sie /dev/urandomstattdessen zu wechseln , was garantiert nicht blockiert.

Um dies global zu tun, bearbeiten Sie die zu verwendende Datei jre/lib/security/java.securityin Ihrer Standard-Java-Installation /dev/urandom(aufgrund eines anderen Fehlers muss sie als angegeben werden /dev/./urandom).

So was:

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

Dann müssen Sie es nie in der Befehlszeile angeben.


Hinweis: Wenn Sie Kryptografie betreiben, benötigen Sie eine gute Entropie. Ein typisches Beispiel: Das Problem mit Android PRNG hat die Sicherheit von Bitcoin-Geldbörsen verringert.


Ihre Antwort wurde positiv bewertet, aber " /dev/randomist per Definition langsam (und kann sogar blockieren)" ist falsch. Dies hängt vollständig von der Systemkonfiguration ab. Neuere Maschinen haben möglicherweise ein schnelles RNG in der CPU, das verwendet werden kann, und BSD-Maschinen haben im Allgemeinen die gleiche Implementierung für /dev/randomund /devl/urandom. Trotzdem sollten Sie sich wahrscheinlich nicht unbedingt darauf verlassen /dev/random , schnell zu sein. Auf VMs möchten Sie möglicherweise das Client-Toolset auf der Client-VM installieren, damit das RNG des Host-Betriebssystems verwendet werden kann.
Maarten Bodewes

17

Ich hatte ein ähnliches Problem mit SecureRandomBlockierungsaufrufen für jeweils etwa 25 Sekunden auf einem kopflosen Debian-Server. Ich habe den havegedDaemon installiert, um sicherzustellen, dass er /dev/randomimmer aufgeladen ist. Auf kopflosen Servern benötigen Sie so etwas, um die erforderliche Entropie zu generieren. Meine Anrufe SecureRandomdauern jetzt vielleicht Millisekunden.


4
apt-get install hasged dann update-rc.d hasged Standardeinstellungen
Rod Lima

11

Wenn Sie eine wirklich "kryptografisch starke" Zufälligkeit wünschen, benötigen Sie eine starke Entropiequelle. /dev/randomist langsam, da es darauf warten muss, dass Systemereignisse Entropie erfassen (Festplattenlesevorgänge, Netzwerkpakete, Mausbewegungen, Tastendrücke usw.).

Eine schnellere Lösung ist ein Hardware-Zufallszahlengenerator. Möglicherweise ist bereits eine in Ihr Motherboard integriert. In der Dokumentation zu hw_random finden Sie Anweisungen, wie Sie herausfinden können, ob Sie es haben und wie Sie es verwenden. Das rng-tools-Paket enthält einen Daemon, in den Hardware-generierte Entropie eingespeist wird /dev/random.

Wenn auf Ihrem System kein HRNG verfügbar ist und Sie bereit sind, die Entropiestärke für die Leistung zu opfern, sollten Sie ein gutes PRNG mit Daten aus erstellen /dev/randomund das PRNG den Großteil der Arbeit erledigen lassen. In SP800-90 sind mehrere NIST-zugelassene PRNGs aufgeführt, die einfach zu implementieren sind.


Guter Punkt, aber mein Code ist Teil einer kommerziellen Anwendung. Ich habe keine Kontrolle über die Serverumgebung. Ich denke, die Zielserver sind immer ohne Maus und Tastatur und verlassen sich für die Entropie vollständig auf Festplatten- und Netzwerk-E / A, was wahrscheinlich das Hauptproblem ist.
David G

3
Ich entdeckte, dass / dev / random von Systemereignissen abhängig war. Als vorübergehende Problemumgehung bewegte ich meine Maus einfach hin und her, während mein Test lief ...
David K

Dieser 82802-Hub für den i820-Chipsatz war schmerzhaft langsam (RIP). Ich bin erstaunt, dass Sie daraus alles Nützliche ziehen können. Ich glaube, ich habe mehr Zeit damit verbracht, es zu blockieren, als Oktette zu sammeln.
Jww

6

Unter Verwendung von Java 8 stellte ich fest, dass SecureRandom.getInstanceStrong()mir unter Linux der NativePRNGBlockingAlgorithmus den Algorithmus geben würde . Dies blockierte oft für viele Sekunden, um ein paar Bytes Salz zu erzeugen.

Ich habe NativePRNGNonBlockingstattdessen explizit nachgefragt und wie vom Namen erwartet, wurde es nicht mehr blockiert. Ich habe keine Ahnung, welche Auswirkungen dies auf die Sicherheit hat. Vermutlich kann die nicht blockierende Version nicht garantieren, wie viel Entropie verwendet wird.

Update : Ok, ich habe diese hervorragende Erklärung gefunden .

Um es nicht zu blockieren, verwenden Sie es auf den Punkt gebracht new SecureRandom(). Dies verwendet /dev/urandom, was nicht blockiert und im Grunde so sicher ist wie /dev/random. Aus dem Beitrag: "Das einzige Mal, dass Sie / dev / random aufrufen möchten, ist, wenn die Maschine zum ersten Mal startet und sich noch keine Entropie angesammelt hat."

SecureRandom.getInstanceStrong() gibt Ihnen das absolut stärkste RNG, aber es ist nur in Situationen sicher, in denen eine Reihe von Blockierungen Sie nicht beeinträchtigt.


1
Ich würde nur Langzeitschlüssel zulassen getInstanceStrong() , beispielsweise für TLS-Zertifikate. Und selbst dann würde ich lieber new SecureRandom()einen FIPS-kompatiblen Schlüsselpaargenerator oder Zufallszahlengenerator verwenden. Ja, dies liefert eine Antwort, wenn /dev/urandom es nicht blockiert: Am Ende hängt es immer noch von der Systementropie ab. aber es ist im Allgemeinen ein sehr guter Rat . Wenn /dev/urandomSie blockieren, müssen Sie möglicherweise die Ursache des Problems und nicht Ihre Java-Anwendung beheben.
Maarten Bodewes

5

Es gibt ein Tool (zumindest unter Ubuntu), das künstliche Zufälligkeit in Ihr System einspeist. Der Befehl lautet einfach:

rngd -r /dev/urandom

und vielleicht brauchen Sie vorne einen Sudo. Wenn Sie kein rng-tools-Paket haben, müssen Sie es installieren. Ich habe es versucht und es hat mir definitiv geholfen!

Quelle: matt vs world


2
Dies ist etwas gefährlich, da es die systemweite Schätzung des Entropiepegels des Linux-Kernels vollständig deaktiviert. Ich denke zu Testzwecken (liest: Jenkins, der die Testsuite einer App ausführt) mit /dev/./urandom ist in Ordnung, aber in der Produktion ist es nicht.
Mirabilos

Dies ist eigentlich die einzige Lösung, die für mich funktioniert hat. Ich hatte beim Erstellen eines Android-Projekts mit Gradle auf Jenkins CI ein Problem mit „nicht genug Entropie“, und das Übergeben eines Parameters an den Build half nicht.
Slawischer

Ich musste sudo rngd -r /dev/urandommit sudo apt install rng-toolsin xenial kombinieren
MrMesees

5

Ich stand vor dem gleichen Problem . Nach einigem Googeln mit den richtigen Suchbegriffen bin ich auf diesen schönen Artikel über DigitalOcean gestoßen .

hasged ist eine mögliche Lösung, ohne Kompromisse bei der Sicherheit einzugehen.

Ich zitiere hier lediglich den relevanten Teil aus dem Artikel.

Basierend auf dem HAVEGE-Prinzip und zuvor basierend auf der zugehörigen Bibliothek ermöglicht hasged die Erzeugung von Zufälligkeit basierend auf Variationen der Codeausführungszeit auf einem Prozessor. Da es nahezu unmöglich ist, dass ein Codeteil genau dieselbe Zeit für die Ausführung benötigt, selbst in derselben Umgebung auf derselben Hardware, sollte der Zeitpunkt für die Ausführung eines einzelnen oder mehrerer Programme geeignet sein, eine zufällige Quelle zu erstellen. Die Implementierung von hasged setzt die Zufallsquelle Ihres Systems (normalerweise / dev / random) unter Verwendung von Unterschieden im Zeitstempelzähler (TSC) Ihres Prozessors, nachdem eine Schleife wiederholt ausgeführt wurde

So installieren Sie hasged

Befolgen Sie die Schritte in diesem Artikel. https://www.digitalocean.com/community/tutorials/how-to-setup-additional-entropy-for-cloud-servers-using-haveged

Ich habe es hier gepostet


5

Das Problem, auf das Sie verwiesen haben, /dev/randomliegt nicht beim SecureRandomAlgorithmus, sondern bei der verwendeten Zufallsquelle. Die beiden sind orthogonal. Sie sollten herausfinden, welcher der beiden Sie verlangsamt.

Gelegentliche Mathematik-Seite, die Sie verlinkt haben, erwähnt ausdrücklich, dass sie nicht die Quelle der Zufälligkeit ansprechen.

Sie können verschiedene JCE-Anbieter wie BouncyCastle ausprobieren, um festzustellen, ob ihre Implementierung SecureRandomschneller ist.

Eine kurze Suche zeigt auch Linux-Patches, die die Standardimplementierung durch Fortuna ersetzen. Ich weiß nicht viel mehr darüber, aber Sie können gerne nachforschen.

Ich sollte auch erwähnen, dass es zwar sehr gefährlich ist, einen schlecht implementierten SecureRandomAlgorithmus und / oder eine Zufallsquelle zu verwenden, Sie jedoch Ihren eigenen JCE-Provider mit einer benutzerdefinierten Implementierung von rollen können SecureRandomSpi. Sie müssen einen Prozess mit Sun durchlaufen, um Ihren Provider signieren zu lassen, aber das ist eigentlich ziemlich einfach. Sie müssen ihnen lediglich ein Formular faxen, aus dem hervorgeht, dass Sie die US-Exportbeschränkungen für Kryptobibliotheken kennen.


Diese verschiedenen JCE-Anbieter sind nur dann von Nutzen, wenn sie eine andere Entropiequelle verwenden, was im Grunde bedeutet, dass sie eine bestimmte Hardware wie ein HSM verwenden müssen. Andernfalls kommt es genauso wahrscheinlich zu Verlangsamungen, je nachdem, wie viel Entropie sie aus dem System extrahieren.
Maarten Bodewes

3

Verwenden Sie den sicheren Zufall als Initialisierungsquelle für einen wiederkehrenden Algorithmus. Sie könnten dann einen Mersenne-Twister für die Massenarbeit verwenden, anstatt den in UncommonMath, der schon eine Weile existiert und sich als besser als andere Prng erwiesen hat

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

Stellen Sie sicher, dass Sie ab und zu den für die Initialisierung verwendeten sicheren Zufall aktualisieren. Sie können beispielsweise einen sicheren Zufall pro Client generieren lassen, indem Sie einen Mersenne-Twister-Pseudozufallsgenerator pro Client verwenden, um einen ausreichend hohen Randomisierungsgrad zu erzielen


2
Diese Antwort ist falsch: Der Mersenne-Twister ist kein sicherer Zufallsgenerator. Es wäre ein guter Algorithmus für Random, aber nicht für SecureRandom.
Maarten Bodewes

3

Gemäß der Dokumentation werden die verschiedenen von SecureRandom verwendeten Algorithmen in der Reihenfolge ihrer Präferenz verwendet:

  • Auf den meisten * NIX-Systemen
    1. NativePRNG
    2. SHA1PRNG
    3. NativePRNGBlocking
    4. NativePRNGNonBlocking
  • Auf Windows-Systemen
    1. SHA1PRNG
    2. Windows-PRNG

Da Sie nach Linux gefragt haben, ignoriere ich die Windows-Implementierung und auch SunPKCS11, das nur unter Solaris wirklich verfügbar ist, es sei denn, Sie haben es selbst installiert - und dann würden Sie dies nicht fragen.

Nach derselben Dokumentation werden diese Algorithmen verwendet

SHA1PRNG Das
anfängliche Seeding erfolgt derzeit über eine Kombination von Systemattributen und dem Entropiesammelgerät java.security.

NativePRNG
nextBytes() verwendet /dev/urandom
generateSeed()Verwendungen/dev/random

NativePRNGBlocking
nextBytes() und generateSeed()Verwendung/dev/random

NativePRNGNonBlocking
nextBytes() und generateSeed()Verwendung/dev/urandom

Das heißt, wenn Sie verwenden SecureRandom random = new SecureRandom(), wird diese Liste durchsucht, bis eine funktionierende gefunden wird, bei der es sich normalerweise um NativePRNG handelt. Und das bedeutet, dass es sich selbst aussät /dev/random(oder dies verwendet, wenn Sie explizit einen /dev/urandomStartwert generieren) und dann zum Abrufen der nächsten Bytes, Ints, Double, Booleschen Werte, What-Have-Yous verwendet.

Da /dev/randomblockiert (es blockiert, bis genügend Entropie im Entropiepool vorhanden ist), kann dies die Leistung beeinträchtigen.

Eine Lösung dafür ist die Verwendung von etwas wie Hged, um genügend Entropie zu erzeugen, eine andere Lösung verwendet /dev/urandomstattdessen. Während Sie , dass für die gesamte Jvm, eine bessere Lösung macht es für diese bestimmte Instanz einstellen könnte SecureRandom, unter Verwendung SecureRandom random = SecureRandom.getInstance("NativePRNGNonBlocking"). Beachten Sie, dass diese Methode bei NativePRNGNonBlocking eine NoSuchAlgorithmException auslösen kann. Seien Sie also bereit, auf die Standardeinstellung zurückzugreifen.

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

Beachten Sie auch, dass sich andere * nix-Systeme /dev/urandommöglicherweise anders verhalten .


Ist /dev/urandomzufällig genug?

Konventionelle Weisheit besagt, dass nur /dev/randomzufällig genug ist. Einige Stimmen unterscheiden sich jedoch. In "Der richtige Weg, SecureRandom zu verwenden" und "Mythen über / dev / urandom" wird argumentiert, dass dies /dev/urandom/genauso gut ist.

Die Benutzer auf dem Informationssicherheitsstapel stimmen dem zu . Grundsätzlich /dev/urandomist es für Ihren Zweck in Ordnung , wenn Sie fragen müssen .


2

Ich bin selbst nicht auf dieses Problem gestoßen, aber ich habe beim Programmstart einen Thread erzeugt, der sofort versucht, einen Startwert zu generieren, und dann stirbt. Die Methode, die Sie für Zufälle aufrufen, wird diesem Thread hinzugefügt, wenn er aktiv ist, sodass der erste Aufruf nur blockiert wird, wenn er sehr früh in der Programmausführung auftritt.


Es ist ein ziemlich extremer Hack, aber es könnte funktionieren; Es wird nicht gesagt, dass das verwendete PRNG möglicherweise kein zusätzliches Saatgut verwendet, was immer noch zu einer Blockierung führen könnte. Die Verwendung einer anderen Zufallszahl, die die Entropie im System bereitstellt oder festlegt, sollte stark bevorzugt werden. Da dies zumindest eine vorübergehende Lösung darstellen kann, habe ich die Antwort dennoch abgelehnt.
Maarten Bodewes

2

Meine Erfahrung war nur mit der langsamen Initialisierung des PRNG, nicht mit der Erzeugung von Zufallsdaten danach. Versuchen Sie eine eifrigere Initialisierungsstrategie. Da die Erstellung teuer ist, behandeln Sie sie wie einen Singleton und verwenden Sie dieselbe Instanz erneut. Wenn für eine Instanz zu viele Thread-Konflikte auftreten, bündeln Sie sie oder machen Sie sie threadlokal.

Gehen Sie bei der Generierung von Zufallszahlen keine Kompromisse ein. Eine Schwäche dort gefährdet Ihre gesamte Sicherheit.

Ich sehe nicht viele COTS-Generatoren auf der Basis des atomaren Zerfalls, aber es gibt verschiedene Pläne für sie, wenn Sie wirklich viele zufällige Daten benötigen. Eine Seite, die immer interessante Dinge zu sehen hat, einschließlich HotBits, ist John Walkers Fourmilab.


1
Ich habe mich immer darüber gewundert, da hadronische Tau-Zerfallsprodukte fast das Ideal einer randomisierten Quelle erreichen. Ich kann meinen Wunsch, dies anstelle von algorithmischen Werkzeugen zu verwenden, einfach nicht loswerden. Aus Gründen der Operation habe ich vor langer Zeit entschieden, dass einige Front-End-Zeiten für alle sicheren Tools endemisch sind. Wenn man einen Randomizer benötigt, der im Konstruktor aufgerufen werden kann und nur daran denkt, einen beim Laden der Seite zu erstellen, ist er unter dem AVL-Swap-In vergraben und selbst so wählerisch wie ich, bleibt er unbemerkt.
Nicholas Jordan

Intel 8xx-Chipsätze (und wahrscheinlich viele andere) verfügen über ein Hardware-RNG, das thermisches Rauschen verwendet, einen wirklich unvorhersehbaren Quanteneffekt. Vertrauenswürdige Plattformmodule können auch Hardware-RNGs enthalten, die in meinem Laptop jedoch leider nicht.
Erickson

Es hängt vom spezifischen RNG ab, ob es einmal sät oder nach einer Weile erneut sät. NIST gibt PRNGs an, die erneut gesät werden, viele Softwareimplementierungen jedoch nicht. Die Umstrukturierung des Codes um einen Singleton ist eine schreckliche Idee, insbesondere bei Multithread-Implementierungen. Es ist besser, die Ursache des Problems zu beheben: die langsame Aussaat aufgrund mangelnder Entropie. Wenn Sie einen Singleton verwenden, verwenden Sie ihn, um Startwerte für andere SecureRandom-Implementierungen bereitzustellen, die vollständig deterministisch sind. Diese Art von Design erfordert jedoch wahrscheinlich einige Kenntnisse.
Maarten Bodewes

@ MaartenBodewes Das sind gute Punkte. Wenn die Implementierung blockiert und auf die Systementropie wartet, ist es meiner Meinung nach keine schreckliche Idee, sie als Singleton in Ihrer Anwendung zu behandeln, da die zugrunde liegende Quelle effektiv ein Singleton ist. Aber diese eine Instanz zu verwenden, um andere zu säen, ist ein guter Vorschlag, auch wenn er komplex ist. Ich bin mir nicht sicher, aber ich denke, dass sich der Sun- (und dann Oracle-) Anbieter für SecureRandomin den letzten 10 Jahren in seiner Entropie-Sammlung ein paar Mal geändert hat.
Erickson

Ich bin mir sehr sicher, dass es sich einige Male geändert hat, so sehr, dass ich nicht versuchen werde, alle Änderungen in diesen Kommentar aufzunehmen :). Es ist weniger wahrscheinlich, dass eine Verlangsamung SecureRandomimmer noch ein Problem ist, aber eine niedrige Entropie in einem System wird immer ein Problem sein. Wenn Sie einen Singleton verwenden, wird stark gekoppelter Code erstellt, der ein Design-Anti-Pattern ist. Es sollte daher mit äußerster Sorgfalt verwendet werden; Sie müssten vorzugsweise alle Verweise im Code umkehren, um das Problem zu beheben.
Maarten Bodewes

2

Es hört sich so an, als ob Sie Ihre RNG-Anforderungen klarer definieren sollten. Die stärkste kryptografische RNG-Anforderung (so wie ich es verstehe) wäre, dass Sie, selbst wenn Sie den Algorithmus kennen, mit dem sie generiert wurden, und Sie alle zuvor generierten Zufallszahlen kennen, keine nützlichen Informationen über eine der in der generierten Zufallszahlen erhalten könnten Zukunft, ohne eine unpraktische Menge an Rechenleistung auszugeben.

Wenn Sie diese vollständige Garantie für Zufälligkeit nicht benötigen, gibt es wahrscheinlich angemessene Leistungskompromisse. Ich würde eher Dan Dyers Antwort zu AESCounterRNG von Uncommons-Maths oder Fortuna zustimmen (einer seiner Autoren ist Bruce Schneier, ein Experte für Kryptographie). Ich habe es auch nie benutzt, aber die Ideen erscheinen auf den ersten Blick seriös.

Ich würde denken , wenn Sie regelmäßig einen anfänglichen zufälligen Startwert generieren könnten (z. B. einmal pro Tag oder Stunde oder was auch immer), könnten Sie eine schnelle Stream-Verschlüsselung verwenden, um Zufallszahlen aus aufeinanderfolgenden Teilen des Streams zu generieren (wenn die Stream-Chiffre XOR verwendet, dann nur Übergeben Sie einen Strom von Nullen oder greifen Sie direkt auf die XOR-Bits zu. ECRYPTs eStreamDas Projekt enthält viele gute Informationen, einschließlich Leistungsbenchmarks. Dies würde die Entropie zwischen den Zeitpunkten, zu denen Sie sie auffüllen, nicht aufrechterhalten. Wenn also jemand eine der Zufallszahlen und den von Ihnen verwendeten Algorithmus kennt, ist es technisch möglicherweise möglich, mit viel Rechenleistung die Stream-Verschlüsselung zu brechen und Erraten Sie den internen Zustand, um zukünftige Zufallszahlen vorhersagen zu können. Sie müssten sich jedoch entscheiden, ob dieses Risiko und seine Folgen ausreichen, um die Kosten für die Aufrechterhaltung der Entropie zu rechtfertigen.

Bearbeiten: Hier sind einige kryptografische Kursnotizen zu RNG, die ich im Internet gefunden habe und die für dieses Thema sehr relevant aussehen.


1
"Fortuna (einer seiner Autoren ist Bruce Schneier, ein Experte für Kryptographie)" - und der andere ist Niels Ferguson, ein Experte für Kryptographie :-)
Steve Jessop

2

Wenn Ihre Hardware dies unterstützt, verwenden Sie das Java RdRand-Dienstprogramm, dessen Autor ich bin.

Es basiert auf Intels RDRANDAnweisungen und ist ungefähr zehnmal schneller als SecureRandomund ohne Bandbreitenprobleme bei der Implementierung großer Volumes.


Beachten Sie, dass diese Implementierung nur auf den CPUs funktioniert, die den Befehl bereitstellen (dh wenn das rdrandProzessorflag gesetzt ist). Sie müssen es explizit über den RdRandRandom()Konstruktor instanziieren . Es wurde kein spezifisches Providerimplementiert.


3
Vielleicht möchten Sie lesen people.umass.edu/gbecker/BeckerChes13.pdf und achten Sie darauf, nie verwenden nur Intel RDRAND Daten. Mischen Sie es immer mit anderen unvorhersehbaren Daten, wie z. B. der Ausgabe einer aRC4-Stream-Verschlüsselung (aus / dev / urandom und mit den ersten KiB der Ausgabe, die aufgrund ihrer bekannten Verzerrung weggeworfen wurden).
Mirabilos

+1 Mirabilos. Ich denke, es RDRANDist eine gute Quelle, aber es ist ein bisschen nicht vertrauenswürdig. Es muss definitiv eine Eingabe von vielen in einen Sammler sein (keine Beleidigung für David Johnston).
Jww

Ich habe abgestimmt, den Link repariert und Hintergrundinformationen bereitgestellt. Wenn Sie nicht einverstanden sind, setzen Sie die Bearbeitung zurück.
Maarten Bodewes

1

Etwas anderes zu betrachten ist die Eigenschaft securerandom.source in der Datei lib / security / java.security

Die Verwendung von / dev / urandom anstelle von / dev / random kann einen Leistungsvorteil haben. Denken Sie daran, wenn die Qualität der Zufallszahlen wichtig ist, gehen Sie keine Kompromisse ein, die die Sicherheit beeinträchtigen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.