1. 概要

Java仮想マシン(JVM)を起動するとき、JVMの動作を変更するさまざまなプロパティを定義できます。 そのようなプロパティの1つは、java.security.egd。です。

このチュートリアルでは、それが何であるか、それをどのように使用するか、そしてそれがどのような効果をもたらすかを調べます。

2. java .security.egd とは何ですか?

JVMプロパティとして、 java.security.egd を使用して、SecureRandomクラスの初期化方法に影響を与えることができます。

すべてのJVMプロパティと同様に、JVMを起動するときに、コマンドラインで-Dパラメーターを使用して宣言します。

java -Djava.security.egd=file:/dev/urandom -cp . com.baeldung.java.security.JavaSecurityEgdTester

通常、Java 8以降を実行していて、Linuxで実行している場合、JVMはデフォルトで file:/ dev /urandomを使用します。

3. java .security.egd にはどのような影響がありますか?

SecureRandom からバイトを読み取る最初の呼び出しを行うと、JVMの java.security構成ファイルを初期化して読み取ります。これファイルにsecurerandom.sourceプロパティが含まれています

securerandom.source=file:/dev/random

デフォルトのsun.security.provider.Sunなどのセキュリティプロバイダーは、を初期化するときにこのプロパティを読み取ります。

java.security.egd JVMプロパティを設定すると、セキュリティプロバイダーはそれを使用して、securerandom.sourceで構成されたプロパティをオーバーライドする場合があります。

java.security.egdsecurerandom.sourceは、エントロピー収集デバイス(EGD)を使用するときにシードデータのメインソースとして使用することを制御します。 SecureRandomでランダムな数値を生成します。

Java 8までは、 $ JAVA _HOME / jre / lib / securityjava.security がありますが、それ以降の実装では、$にあります。 JAVA _HOME / conf /security

egd オプションが効果を発揮するかどうかは、セキュリティプロバイダーの実装によって異なります。

4. java .security.egd はどのような値を取ることができますか?

java.security.egd は、次のような値のURL形式で指定できます。

  • ファイル:/ dev / random
  • ファイル:/ dev / urandom
  • ファイル:/dev/./urandom

この設定が効果を発揮するか、他の値が違いを生むかは、プラットフォームと使用しているJavaのバージョン、およびJVMのセキュリティがどのように構成されているかによって異なります。

Unixベースのオペレーティングシステム(OS)では、 / dev / random は、ファイルシステムに通常のファイルとして表示される特別なファイルパスですが、そこから読み取ると、実際にはOSのデバイスドライバーと対話して乱数を生成します。 。 一部のデバイス実装では、 / dev /urandomおよび/dev / arandomURIを介したアクセスも提供されます。

5. file:/dev/./urandom の何が特別なのですか?

まず、ファイル / dev /random/dev / urandom:の違いを理解しましょう。

  • / dev / random は、さまざまなソースからエントロピーを収集します。 / dev / random は、予測できないデータで読み取り要求を満たすのに十分なエントロピーが得られるまでブロックします
  • / dev / urandom は、ブロックせずに、利用可能なものから疑似ランダム性を導き出します。

SecureRandom を最初に使用すると、デフォルトのSun SeedGeneratorが初期化されます。

特別な値file:/ dev / randomまたはfile:/ dev / urandom のいずれかを使用すると、Sun SeedGenerator はネイティブ(プラットフォーム)の実装。

Unixでのプロバイダーの実装は、 / dev /randomから読み取ることでブロックされる場合があります。 Java 1.4では、この問題が発生する実装がいくつか発見されました。 その後、このバグはJava8のJDK拡張提案(JEP 123)で修正されました。

file:/dev/./urandomなどのURL、またはその他の値を使用すると、SeedGeneratorはそれを使用するシードソースへのURLとして扱います

Unixライクなシステムでは、 file:/dev/./urandomURLは同じ非ブロッキング/dev /urandomファイルに解決されます。

ただし、常にこの値を使用する必要はありません。 Windowsでは、このファイルがないため、URLを解決できません。 これにより、ランダム性を生成する最終メカニズムがトリガーされ、初期化が約5秒遅れる可能性があります。

6. SecureRandomの進化

java.security.egd の効果は、さまざまなJavaリリースを通じて変更されました。

それでは、SecureRandomの動作に影響を与えたいくつかのより重要なイベントを見てみましょう。

SecureRandom がどのように変更されたかを理解することで、java.security.egdプロパティの予想される影響についての洞察が得られます。

7. java.security.egdの効果のテスト

JVMプロパティの効果を確認する最良の方法は、それを試すことです。 そこで、は、コードを実行して新しい SecureRandom を作成し、 someを取得するのにかかる時間を計って、java.security.egdの効果を見てみましょう。ランダムバイト。

まず、 main()メソッドを使用してJavaSecurityEgdTesterクラスを作成しましょう。 System.nanoTime()を使用して secureRandom.nextBytes()の呼び出しの時間を計り、結果を表示します。

public class JavaSecurityEgdTester {
    public static final double NANOSECS = 1000000000.0;

    public static void main(String[] args) {
        SecureRandom secureRandom = new SecureRandom();
        long start = System.nanoTime();
        byte[] randomBytes = new byte[256];
        secureRandom.nextBytes(randomBytes);
        double duration = (System.nanoTime() - start) / NANOSECS;

        System.out.println("java.security.egd = " + System.getProperty("java.security.egd") + " took " + duration + " seconds and used the " + secureRandom.getAlgorithm() + " algorithm");
    }
}

次に、新しいJavaインスタンスを起動し、 java .security.egd プロパティの値を指定して、 JavaSecurityEgdTesterテストを実行しましょう。

java -Djava.security.egd=file:/dev/random -cp . com.baeldung.java.security.JavaSecurityEgdTester

出力をチェックして、テストにかかった時間と使用されたアルゴリズムを確認しましょう。

java.security.egd=file:/dev/random took 0.692 seconds and used the SHA1PRNG algorithm

システムプロパティは初期化時にのみ読み取られるため、 java.security.egdの異なる値ごとに新しいJVMでクラスを起動しましょう。

java -Djava.security.egd=file:/dev/urandom -cp . com.baeldung.java.security.JavaSecurityEgdTester
java -Djava.security.egd=file:/dev/./urandom -cp . com.baeldung.java.security.JavaSecurityEgdTester
java -Djava.security.egd=baeldung -cp . com.baeldung.java.security.JavaSecurityEgdTester

Java8またはJava11を使用するWindowsでは、値 file:/ dev / random またはfile:/ dev /urandomを使用したテストで1秒未満の時間が得られます。 file:/dev/./urandom 、さらには baeldung など、他のものを使用すると、テストに5秒以上かかります。

これが発生する理由の説明については、前のセクションを参照してください。 Linuxでは、異なる結果が得られる可能性があります。

8. SecureRandom.getInstanceStrong()はどうですか?

Java 8では、 SecureRandom.getInstanceStrong()メソッドが導入されました。 それが結果にどのように影響するか見てみましょう。

まず、新しいSecureRandom()SecureRandomに置き換えましょう。 getInstanceStrong()

SecureRandom secureRandom = SecureRandom.getInstanceStrong();

それでは、テストをもう一度実行してみましょう。

java -Djava.security.egd=file:/dev/random -cp . com.baeldung.java.security.JavaSecurityEgdTester

Windowsで実行する場合、SecureRandom.getInstanceStrong()を使用すると、java.security.egdプロパティの値に認識できる影響はありません。 認識されない値でも、迅速な応答が得られます。

出力をもう一度確認して、0.01秒未満の時間に注目してみましょう。 また、アルゴリズムがWindows-PRNGになったことを確認しましょう。

java.security.egd=baeldung took 0.003 seconds and used the Windows-PRNG algorithm

アルゴリズムの名前のPRNGは、疑似乱数ジェネレーターを表すことに注意してください。

9. アルゴリズムのシード

ランダムな数字は安全な鍵の暗号化で頻繁に使用されるため、予測できない必要があります。

したがって、アルゴリズムをシードする方法は、アルゴリズムが生成するランダム数の予測可能性に直接影響します。

予測不可能性を生成するために、SecureRandom実装は、蓄積された入力から収集されたエントロピーを使用してアルゴリズムをシードします。これは、マウスやキーボードなどのIOデバイスに由来します。

Unixライクなシステムでは、エントロピーはファイル/ dev /randomに蓄積されます。

Windowsには/dev /randomファイルはありません。-Djava.security.egdをfile:/ dev / randomまたはfile:/ dev/urandomに設定するとデフォルトになりますネイティブのMicrosoftCryptoAPIを使用してをシードするアルゴリズム(SHA1PRNG)。

10. 仮想マシンはどうですか?

/ dev / random にエントロピーがほとんどまたはまったく収集されていない仮想マシンで、アプリケーションが実行されている場合があります。

仮想マシンにはデータを生成するための物理的なマウスまたはキーボードがないため / dev /randomのエントロピーの蓄積ははるかに遅くなります。 これにより、デフォルトのSecureRandom呼び出しが、予測できない数を生成するのに十分なエントロピーが発生するまでブロックされる可能性があります

これを軽減するために実行できる手順があります。 たとえば、RedHat LinuxでVMを実行している場合、システム管理者は仮想IO乱数ジェネレーターvirtio-rng構成できます。 これは、ホストされている物理マシンからエントロピーを読み取ります。

11. トラブルシューティングのヒント

アプリケーションまたはその依存関係がSecureRandom番号を生成するときにアプリケーションがハングする場合は、 java .security.egd を検討してください。特に、Linuxで実行している場合、および以前のJava8で実行されています。

当社のSpringBootアプリケーションは、多くの場合、組み込みの Tomcatを使用します。 これは、SecureRandomを使用してセッションキーを生成します。 Tomcatの「SecureRandomインスタンスの作成」操作に5秒以上かかる場合は、 java.security.egd。に異なる値を試す必要があります。

12. 結論

このチュートリアルでは、JVMプロパティ java.security.egd とは何か、その使用方法、およびその効果について学習しました。 また、その効果は、実行しているプラットフォームと使用しているJavaのバージョンによって異なる可能性があることもわかりました。

最後に、 SecureRandom と、それがどのように機能するかについては、JCAリファレンスガイドSecureRandomセクションとSecureRandomAPI仕様を参照してください。 urandomに関する神話のいくつかの。

いつものように、コードはGitHubにあります。