Java-Anwendungen können und sollten die Klasse java.security.SecureRandom verwenden , um mithilfe eines kryptografisch starken Pseudozufallszahlengenerators ( CSPRNG ) kryptografisch starke Zufallswerte zu erzeugen . Die Standard-JDK-Implementierungen der Klasse java.util.Random werden nicht als kryptografisch stark angesehen.
Unix-ähnliche Betriebssysteme verfügen über /dev/randomeine spezielle Datei, die Pseudozufallszahlen bereitstellt , die auf Umgebungsgeräusche zugreifen, die von Gerätetreibern und anderen Quellen gesammelt wurden. Es wird jedoch blockiert, wenn weniger Entropie verfügbar ist als angefordert . /dev/urandomIn der Regel wird nie blockiert, selbst wenn der Startwert des Pseudozufallszahlengenerators seit dem Start nicht vollständig mit Entropie initialisiert wurde. Es gibt noch eine dritte spezielle Datei, /dev/arandomdie nach dem Booten blockiert, bis der Startwert mit genügend Entropie sicher initialisiert wurde, und dann nie wieder blockiert.
Standardmäßig setzt die JVM die SecureRandom- Klasse mit /dev/random, daher kann Ihr Java-Code unerwartet blockieren . Die Option -Djava.security.egd=file:/dev/./urandomim Befehlszeilenaufruf zum Starten des Java-Prozesses weist die JVM an, /dev/urandomstattdessen zu verwenden .
Das Extra /./scheint die JVM dazu zu bringen, den SHA1PRNG-Algorithmus zu verwenden, der SHA-1 als Grundlage für den PRNG (Pseudo Random Number Generator) verwendet. Es ist stärker als der NativePRNG-Algorithmus, der bei /dev/urandomAngabe verwendet wird.
Schließlich gibt es einen Mythos, der /dev/urandomein Pseudozufallszahlengenerator, ein PRNG, /dev/randomist , während er ein "wahrer" Zufallszahlengenerator ist . Dies ist einfach nicht wahr, beide /dev/randomund /dev/urandomwerden von demselben CSPRNG (kryptografisch sicherer Pseudozufallszahlengenerator) gespeist. Nur das Verhalten, wenn ihrem jeweiligen Pool die Entropie ausgeht, unterscheidet sich nach einigen Schätzungen: /dev/randomBlöcke, während /dev/urandomdies nicht der Fall ist.
Was ist mit der Entropie, die zur Neige geht? Es spielt keine Rolle.
Es stellt sich heraus, dass „zufällig aussehen“ die Grundvoraussetzung für viele unserer kryptografischen Bausteine ist. Und wenn Sie die Ausgabe eines kryptografischen Hashs nehmen, muss dieser nicht von einer zufälligen Zeichenfolge zu unterscheiden sein, damit die Chiffren ihn akzeptieren. Dies ist der Grund für die Verwendung des SHA1PRNG-Algorithmus, da er eine Hash-Funktion und einen Zähler zusammen mit einem Startwert verwendet.
Wann soll angewendet werden?
Immer würde ich sagen.
Quellen:
https://gist.github.com/svrc/5a8accc57219b9548fe1
https://www.2uo.de/myths-about-urandom
EDIT 04/2020:
In einem Kommentar wird eine Änderung des Verhaltens der SecureRandom- Klasse in Java 8 erwähnt.
SHA1PRNG und NativePRNG wurden behoben, um die Eigenschaften der SecureRandom-Seed-Quelle in der Datei java.security ordnungsgemäß zu berücksichtigen. (Die obskure Problemumgehung mit file: /// dev / urandom und file: / dev /./ urandom ist nicht mehr erforderlich.)
Dies wurde bereits durch die Tests hervorgehoben, auf die im obigen Abschnitt Quellen verwiesen wird. Das Extra /./ist erforderlich, um den von SecureRanom in Java 8 verwendeten Algorithmus von NativePRNG auf SHA1PRNG zu ändern.
Ich habe jedoch einige Neuigkeiten, die ich gerne teilen möchte. Gemäß der JEP-273 , da Java 9 die Secure Klasse implementiert die drei Determinis Zufallsbitgenerators (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 zwei Arten von SecureRandom- Implementierungen:
- Eine davon ist plattformabhängig und basiert auf nativen Aufrufen oder Betriebssystemgeräten wie dem Lesen
/dev/{u}randomunter Unix oder der Verwendung von CryptoAPI unter Windows. Die neuesten Versionen von Linux und Windows unterstützen DRBG bereits, ältere Versionen und eingebettete Systeme jedoch 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 von genehmigten DRBG-Mechanismen verwendeten Algorithmen.
In der Zwischenzeit lautet das Java 13 Security Developer's Guide noch
Wenn unter Linux und macOS das Entropieerfassungsgerät in java.security auf file:/dev/urandomoder file:/dev/randomeingestellt ist, wird NativePRNG SHA1PRNG vorgezogen. Andernfalls wird SHA1PRNG bevorzugt.
Um zu verdeutlichen, wie die neuen DRBG-Mechanismen mit den vorherigen PRNGs zusammenspielen, führe ich mit AdoptOpenJDK (Build 13.0.2 + 8) einige Tests unter macOS (Darwin) durch. Hier sind die Ergebnisse:
Datei: / dev / random
Reihenfolge der Präferenzen für Anbieter:
SecureRandom.NativePRNG
SecureRandom.DRBG
SecureRandom.SHA1PRNG
Datei: / dev / urandom
Präferenzreihenfolge für Anbieter:
SecureRandom.NativePRNG
SecureRandom.DRBG
SecureRandom.SHA1PRNG
Datei: / dev /./ urandom
Reihenfolge der Präferenzen für Anbieter:
SecureRandom.DRBG
SecureRandom.SHA1PRNG
SecureRandom.NativePRNG
Fazit:
Ich würde empfehlen, -Djava.security.egd=file:/dev/./urandomdiese Option zu verwenden , um sicherzustellen, dass die stärkste verfügbare SecureRandom- Implementierung unabhängig von der verwendeten Plattform genutzt wird, ohne dass der Code unerwartet blockiert wird.