SecureRandom.getInstanceStrong() で使われる乱数生成のアルゴリズムを調べてみた
概要
Java 8 から java.security.SecureRandom クラスに追加された getInstanceStrong() というメソッドについて調べてみました。
SecureRandom とは
暗号鍵の生成などで安全に使える乱数を生成するための java.security.SecureRandom というクラスがあります。
この SecureRandom を使う場合、Java 7 以前はプラットフォームごとのデフォルトのアルゴリズムで使用するか、明示的に使用するアルゴリズムを指定していました。
Java 8 からは実行するプラットフォームで使える一番安全なアルゴリズムで初期化されたインスタンスを返す getInstanceStrong() というメソッドが追加されたので、その挙動を調べてみました。
テストコード
SecureRandomTest.java
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class SecureRandomTest
{
public static void main(String[] args)
{
try
{
SecureRandom random = SecureRandom.getInstanceStrong();
System.out.println("SecureRandom.getInstanceStrong() = " + random.getAlgorithm());
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
}
}
実行結果
Amazon Linux
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class SecureRandomTest
{
public static void main(String[] args)
{
try
{
SecureRandom random = SecureRandom.getInstanceStrong();
System.out.println("SecureRandom.getInstanceStrong() = " + random.getAlgorithm());
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
}
}
Amazon Linux
AmazonLinux 2016.03 + OpenJDK 1.8.0_91
=> SecureRandom.getInstanceStrong() = NativePRNGBlocking
CentOS
CentOS Linux 7.2.1511 + OpenJDK 1.8.0_91
=> SecureRandom.getInstanceStrong() = NativePRNGBlocking
Mac
OS X El Capitan 10.11.5 + Java 1.8.0_65
=> SecureRandom.getInstanceStrong() = NativePRNGBlocking
Windows
Windows 8.1 Professional + Java 1.8.0_92
=> SecureRandom.getInstanceStrong() = Windows-PRNG
'NativePRNGNonBlocking' を明示的に指定すると java.security.NoSuchAlgorithmException が発生
使用できるアルゴリズムと優先順位
各プラットフォームで使用できるアルゴリズムとデフォルトの優先順位はこのドキュメントにある一覧で調べることができます。
Java暗号化アーキテクチャOracleプロバイダのドキュメント(JDK 8用)
しかし、getInstanceStrong() で選択されるアルゴリズムはこの優先順位とは異なっています。
getInstanceStrong() の優先順位は ${JAVA_HOME}/jre/lib/security/java.security の securerandom.strongAlgorithms というプロパティに定義されています。
AmazonLinux
AmazonLinux 2016.03 + OpenJDK 1.8.0_91
securerandom.strongAlgorithms=NativePRNGBlocking:SUN
CentOS
CentOS Linux 7.2.1511 + OpenJDK 1.8.0_91
securerandom.strongAlgorithms=NativePRNGBlocking:SUN
Mac
OS X El Capitan 10.11.5 + Java 1.8.0_65
securerandom.strongAlgorithms=NativePRNGBlocking:SUN
Windows
Windows 8.1 Professional + Java 1.8.0_92
securerandom.strongAlgorithms=Windows-PRNG:SunMSCAPI,SHA1PRNG:SUN
【考察】
常に getInstanceStrong() がベストなのか?
Java 8 から SecureRandom による乱数の生成に以下のアルゴリズムが追加されました。
- NativePRNG
- NativePRNGBlocking
- NativePRNGNonBlocking
このうち Linux や OS X で getInstanceStrong() を実行したときに返ってくる NativePRNGBlocking は、乱数の生成に /dev/random を使用します。
/dev/random は安全な乱数を生成するために十分な量のエントロピーが無い場合は処理がブロックされる(エントロピーが溜まるまで環境ノイズを収集している?)ので、乱数を多く生成する必要がある場合はパフォーマンスの低下に注意が必要です。
これらの新しく追加されたアルゴリズムの実装であるSUNプロバイダが使用する乱数生成器の組み合わせです。
アルゴリズム | generateSeed() | nextBytes() |
---|---|---|
NativePRNG | /dev/random | /dev/urandom |
NativePRNGBlocking | /dev/random | /dev/random |
NativePRNGNonBlocking | /dev/urandom | /dev/urandom |
Java暗号化アーキテクチャOracleプロバイダのドキュメント(JDK 8用)
このように、処理がブロックされない /dev/urandom を組み合わせて使用できるような選択肢が用意されています。
安全な乱数を一つだけ欲しいという場合は getInstanceStrong() を使い、乱数の生成頻度が高くなるに従って、安全面とパフォーマンスのトレードオフを考えながら NativePRNGBlocking > NativePRNG > NativePRNGNonBlocking と選択していくのが良いのではないでしょうか。
Windows の場合
NativePRNG のアルゴリズムは Windows 版のSUNプロバイダには実装されていないので、明示的に指定したコードを Windows で実行するとjava.security.NoSuchAlgorithmException がスローされます。
感想
アルゴリズムを明示的に指定して使おうと思うと、開発環境が Windows で実行環境が Linux みたいなケースでは不便。
現実的な解決方法としては
- 乱数の生成頻度が低い: プラットフォームのデフォルトのアルゴリズムか getInstanceStrong() を使う
- 乱数の生成頻度が高い: 運用時はプラットフォーム毎に最適なアルゴリズムの SecureRandom を返す独自のファクトリクラスを実装する
といったところか。
SecureRandom.getInstanceStrongNonBlocking() のようなメソッドがあるとよいのだけれど。
Author And Source
この問題について(SecureRandom.getInstanceStrong() で使われる乱数生成のアルゴリズムを調べてみた), 我々は、より多くの情報をここで見つけました https://qiita.com/aibax/items/29e09318ac85c4e93c1a著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .