このコードは安全ですか?
SecureRandom randomizer = new SecureRandom(String.valueOf(new Date().getTime()).getBytes());
これは、安全なランダムのシードをインスタンス化する正しい方法ですか?
このコードは安全ですか?
SecureRandom randomizer = new SecureRandom(String.valueOf(new Date().getTime()).getBytes());
これは、安全なランダムのシードをインスタンス化する正しい方法ですか?
いいえ、SecureRandom(byte[])
コンストラクターは避けてください。それは安全ではなく、携帯性もありません。
Windowsと他のオペレーティングシステムでは動作が異なるため、移植性はありません。
ほとんどのOSでは、デフォルトのアルゴリズムは「NativePRNG」です。これは、OSからランダムデータを取得し(通常"/dev/random"
)、指定したシードを無視します。
Windowsでは、デフォルトのアルゴリズムは「SHA1PRNG」です。これは、シードとカウンターを組み合わせて、結果のハッシュを計算します。
入力(ミリ秒単位の現在のUTC時間)の可能な値の範囲が比較的狭いため、これはあなたの例では悪いニュースです。たとえば、攻撃者が過去48時間にRNGがシードされたことを知っている場合、攻撃者はシードを2 28未満の可能な値に絞り込むことができます。つまり、エントロピーは27ビットしかありません。
一方、SecureRandom()
Windowsでデフォルトのコンストラクターを使用した場合は、ネイティブCryptoGenRandom
関数を呼び出して128ビットのシードを取得します。したがって、独自のシードを指定することにより、セキュリティが弱まります。
本当にデフォルトのシードをオーバーライドしたい場合(単体テストなど)、アルゴリズムも指定する必要があります。例えば
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed("abcdefghijklmnop".getBytes("us-ascii"));
「 JavaSecureRandomでパフォーマンスの問題を解決する方法」も参照してください。
およびこのブログ投稿: http: //www.cigital.com/justice-league-blog/2009/08/14/proper-use-of-javas-securerandom/
SecureRandom自体をシードするのが最善だと思います。これは、作成直後にnextBytesを呼び出すことによって行われます(setSeedを呼び出すとこれを防ぐことができます)。
final byte[] dummy = new byte[512];
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.nextBytes(dummy);
デフォルトではないLinuxでも高速なノンブロッキング実装が保証されるため、SHA1PRNGを使用する必要があります。
コードは、ランダマイザーのシードに指定されたシードを使用するだけではないため、かなり安全です。
単に使用するよりもはるかにランダムではありません。
SecureRandom randomizer = new SecureRandom();