In einem Projekt, an dem ich arbeite, wird die Anwendung mit einem ähnlichen Befehl gestartet:
java -Djava.security.egd=file:/dev/urandom -jar app.jar
Ich habe die noch nie gesehen java.security.egd
Möglichkeit vor. Wenn Sie ein wenig suchen, scheint es verwendet zu werden, um die Generierung von Zufallszahlen in einer Java-Anwendung zu konfigurieren.
Ist es richtig? Wann soll es angewendet werden?
TL;DR
Wenn läuft Java 8 auf modernen Betriebssystemen mit Unterstützung für Deterministic Random Bit Generator (DRBG)würde ich die Verwendung empfehlen
-Djava.security.egd=file:/dev/urandom
um zu vermeiden, dass der Code unerwartet blockiert wird. Wenn Sie sich nicht sicher sind, welches Betriebssystem verwendet wird, schlage ich vor, bei der ursprünglichen Empfehlung zu bleiben, nämlich:
-Djava.security.egd=file:/dev/./urandom
Wenn läuft Java11würde ich empfehlen, einfach zu verwenden
-Djava.security.egd=file:/dev/./urandom
um sich zu vergewissern:
- das Stärkste nutzen SecureRandom Implementierung verfügbar (DRBG), unabhängig von der zugrunde liegenden Plattform
- vermeiden, dass der Code unerwartet blockiert wird (
securerandom.source=file:/dev/urandom
)
Lesen Sie weiter, um die Details zu erfahren.
Java-Anwendungen können und sollten verwenden java.security.SecureRandom Klasse zum Erzeugen kryptografisch starker Zufallswerte mithilfe eines kryptografisch starken Pseudozufallszahlengenerators (CSPRNG). Die standardmäßigen JDK-Implementierungen von java.util.Random Klasse gelten nicht als kryptografisch stark.
Unix-ähnliche Betriebssysteme haben /dev/random
, eine spezielle Datei, die Pseudo-Zufallszahlen bereitstellt, die auf Umgebungsgeräusche zugreifen, die von Gerätetreibern und anderen Quellen gesammelt wurden. Jedoch, es blockiert, wenn weniger Entropie verfügbar ist als angefordert; /dev/urandom
blockiert normalerweise nie, selbst wenn der Seed des Pseudozufallszahlengenerators seit dem Booten nicht vollständig mit Entropie initialisiert wurde. Es gibt noch eine 3. Spezialdatei, /dev/arandom
die nach dem Booten blockiert, bis der Seed sicher mit genügend Entropie initialisiert wurde, und dann nie wieder blockiert.
Standardmäßig erstellt die JVM die SecureRandom Klasse verwenden /dev/random
deshalb Ihr Java-Code kann unerwartet blockieren. Die Option -Djava.security.egd=file:/dev/./urandom
im Befehlszeilenaufruf, der zum Starten des Java-Prozesses verwendet wird, teilt der JVM mit, dass sie verwendet werden soll /dev/urandom
stattdessen.
Das Extra /./
scheint die JVM zu nutzen die SHA1PRNG-Algorithmus die SHA-1 als Grundlage des PRNG (Pseudo Random Number Generator) verwendet. Es ist stärker als der NativePRNG-Algorithmus, der wann verwendet wird /dev/urandom
angegeben.
Schließlich gibt es einen Mythos /dev/urandom
ist ein Pseudo-Zufallszahlengenerator, ein PRNG, während /dev/random
ist ein „echter“ Zufallszahlengenerator. Das ist einfach nicht wahr, beides /dev/random
und /dev/urandom
werden von demselben CSPRNG (kryptographisch sicherer Pseudozufallszahlengenerator) gespeist. Nur ihr Verhalten unterscheidet sich: /dev/random
blockiert, wenn seinem Zufallspool nach einer Schätzung die Entropie ausgeht, while /dev/urandom
nicht.
Was ist mit Systemen mit niedriger Entropie? Es ist nicht so schlimm.
Es stellt sich heraus, dass „zufälliges Aussehen“ die Grundvoraussetzung für mehrere kryptografische Komponenten ist, wie z. B. kurzlebige Sitzungsschlüssel von Webservern. Und wenn Sie die Ausgabe eines kryptografischen Hashs nehmen, ist es nicht von einer zufälligen Zeichenfolge zu unterscheiden, sodass Chiffren es akzeptieren. Aus diesem Grund wird der SHA1PRNG-Algorithmus verwendet, da er eine Hash-Funktion und einen Zähler zusammen mit einem Seed verwendet.
Wann soll angewendet werden?
Immer, würde ich sagen.
Quellen:
https://gist.github.com/svrc/5a8acc57219b9548fe1
https://www.2uo.de/myths-about-urandom
EDIT 09/2020:
Ich habe dieses Update geändert, um die Tests widerzuspiegeln mit:
-Java 8 auf modernen Betriebssystemen
-Java 11, da es sich um die aktuelle LTS-Version (Long Term Support) handelt.
Ein Kommentar erwähnt eine Änderung am SecureRandom Klassenverhalten in Java 8.
SHA1PRNG und NativePRNG wurden korrigiert, um die Eigenschaften der SecureRandom-Seed-Quelle in der Datei java.security korrekt zu respektieren. (Der obskure Workaround mit file:///dev/urandom und file:/dev/./urandom ist nicht mehr erforderlich.)
Dies wurde bereits durch die Tests aufgezeigt, auf die im Abschnitt „Quellen“ oben verwiesen wurde. Das Extra /./
ist erforderlich, um den von verwendeten Algorithmus zu ändern SecureRandom in Java 8 von NativePRNG zu SHA1PRNG.
Ich stimme zu, dass NativePRNG sicherer ist als SHA1PRNG, aber nur, wenn es auf modernen Betriebssystemen ausgeführt wird. Ich habe daher mein Fazit entsprechend aktualisiert und nach oben verschoben.
Allerdings habe ich einige Neuigkeiten, die ich gerne teilen möchte. Gemäß der JEP-273seit Java 9 die SecureRandom Klasse implementiert die drei Deterministischer Zufallsbitgenerator (DRBG) Mechanismen beschrieben in NIST 800-90Ar1. Diese Mechanismen implementieren moderne Algorithmen, die so stark sind wie SHA-512 und AES-256.
Das JDK hatte zuvor zwei Arten von SecureRandom Implementierungen:
- Eines ist plattformabhängig und basiert auf nativen Aufrufen oder OS-Geräten wie dem Lesen
/dev/{u}random
unter Unix oder mit der CryptoAPI unter Windows. Die neuesten Versionen von Linux und Windows unterstützen bereits DRBG, aber ältere Versionen und eingebettete Systeme möglicherweise nicht.
- Die andere Art ist eine reine Java-Implementierung, die eine ältere SHA1-basierte RNG-Implementierung verwendet, die nicht so stark ist wie die Algorithmen, die von zugelassenen DRBG-Mechanismen verwendet werden.
Inzwischen die Entwicklerhandbuch für Java 11-Sicherheit liest sich noch
Unter Linux und macOS, wenn das Entropieerfassungsgerät in java.security auf eingestellt ist file:/dev/urandom
oder file:/dev/random
, dann wird NativePRNG gegenüber SHA1PRNG bevorzugt. Andernfalls wird SHA1PRNG bevorzugt.
Um zu verdeutlichen, wie die neuen DRBG-Mechanismen mit den vorherigen PRNGs zusammenspielen, habe ich einige Tests auf macOS (Darwin) mit AdoptOpenJDK (Build 11.0.7+10) durchgeführt. Hier sind die Ergebnisse:
-Djava.security.egd=file:/dev/random
(Dies entspricht der Standardoption)
Standardalgorithmus: NativePRNG
Anbieter: SecureRandom.NativePRNG-Algorithmus von: SUN
-Djava.security.egd=file:/dev/urandom
Standardalgorithmus: NativePRNG
Anbieter: SecureRandom.NativePRNG-Algorithmus von: SUN
-Djava.security.egd=file:/dev/./urandom
Standardalgorithmus: DRBG
Anbieter: SecureRandom.DRBG-Algorithmus von: SUN
Schließlich der Punkt der Verwendung /dev/urandom
als Quelle der Zufälligkeit bleibt auch bei der Verwendung moderner Betriebssysteme von größter Bedeutung, wie wir weiter lesen können dieser sehr interessante Beitrag:
Teilen /dev/random
ist eine Herausforderung für jede Linux-Container-Technologie …
Das Problem der geringen Entropie auf virtualisierten Servern wird verschärft, weil … Linux-Container, die auf demselben Host laufen, um einen begrenzten Vorrat an Entropie konkurrieren. Diese Art von Problem wird manchmal als a bezeichnet stampfende Herde. Das /dev/random
device ist eine knappe gemeinsam genutzte Systemressource, von der Linux-Container-Mandanten wahrscheinlich nicht bemerkt haben, dass sie sie teilen. Wenn sie alle versuchen, es gleichzeitig zu verwenden, verursachen sie effektiv einen Denial-of-Service auf einander.
Quellen:
https://www.openssl.org/blog/blog/2017/08/12/random/
Dies hängt mit dem Unterschied von Linux zusammen /dev/random
und /dev/urandom
Zufallszahlengenerator.
Daraus entnommen Verknüpfung
Java-Bug 6202721 gibt an, dass java.security.SecureRandom /dev/random anstelle von /dev/urandom verwendet, selbst wenn /dev/urandom angegeben ist, da /dev/urandom zu der Zeit (um 2004) nicht richtig funktionierte. Der Fehler wurde nie behoben, da /dev/urandom recht gut funktioniert. Daher müssen Sie es vortäuschen, indem Sie die Einstellung verschleiern, indem Sie /dev/./urandom verwenden, um die Verwendung von SHA1PRNG anstelle von /dev/random zu erzwingen.
Zur Beantwortung Ihrer Frage
Wann soll angewendet werden?
Basierend auf dem obigen Link ist dies etwas Einzigartiges für die Java-Versionen 5 und folgende, das sich aus Problemen mit /dev/urandom auf Linux-Systemen im Jahr 2004 ergab.