1. ホーム

[解決済み】 java.util.Random と java.security.SecureRandom の違いについて

2022-04-08 17:47:43

質問

私のチームは、ランダムなトークンを生成するサーバーサイドのコード(Java)を渡されましたが、私は同じことについて質問があります。

これらのトークンの目的は、セッションID、パスワードリセットリンクなどに使用される、かなり機密性の高いものです。そのため、誰かに推測されたり、ブルートフォースで実行されたりしないように、暗号学的にランダムである必要があります。トークンは64ビットの長さで、quot;long"です。

現在、このコードでは java.util.Random クラスがこれらのトークンを生成します。そのため ドキュメント に対して java.util.Random には、次のように明記されています。

java.util.Randomのインスタンスは暗号学的に安全ではありません。セキュリティに敏感なアプリケーションで使用するための暗号的に安全な擬似乱数生成器を取得するには、代わりにSecureRandomを使用することを検討してください。

しかし、現在のコードでは java.util.Random をインスタンス化することです。 java.security.SecureRandom クラスを作成し SecureRandom.nextLong() メソッドでシードを取得し、それを使って java.util.Random クラスがあります。次に java.util.Random.nextLong() メソッドを使用してトークンを生成します。

そこで質問なのですが java.util.Random を使用してシードされています。 java.security.SecureRandom ? を使用するようにコードを修正する必要がありますか? java.security.SecureRandom はトークンの生成にのみ使用されるのですか?

現在、コードのシードが Random 起動時に一度だけ

解決方法は?

Oracle JDK 7の標準的な実装では、線形合同生成器と呼ばれるものを使用して、ランダムな値を生成するために java.util.Random .

より抜粋 java.util.Random のソースコード (JDK 7u2) のコメントから。 protected int next(int bits) これはランダムな値を生成するものです。

<ブロッククオート

これは、線形合同擬似乱数生成器である。 でD. H. Lehmerが定義し、Donald E. Knuthが記述しています。 コンピュータ・プログラミングの技術 第3巻 半数アルゴリズム 3.2.1項を参照。

線形合同発電機の予測可能性

Hugo Krawczykは、これらのLCGがどのように予測されるかについて、かなり良い論文を書いています("How to predict congruential generators")。もしあなたがラッキーで興味があれば、まだウェブ上でその無料ダウンロード版を見つけることができるかもしれません。そして、もっとたくさんの研究があり、明らかに次のようなことを示しています。 決して セキュリティクリティカルな目的でLCGを使用する。これは、あなたの乱数 セッションIDなどには不要なものです。

線形合同発電機の壊し方

攻撃者はLCGが一巡するのを待つ必要があるという仮定は間違っています。最適なサイクル(その再帰関係における係数m)であっても、フルサイクルよりもはるかに短い時間で将来の値を予測することは非常に簡単です。結局のところ、解く必要があるのはモジュール式の束だけで、LCGの出力値を十分に観測した後はすぐに簡単になるのである。

種が良くても、セキュリティは向上しません。で生成された乱数値で種を蒔いたとしても、それは単に問題ではありません。 SecureRandom あるいは、サイコロを数回振って値を出すことも可能です。

攻撃者は、観測された出力値から単純に種を計算する。これには かなり少ない の場合、2^48よりも時間がかかる。 java.util.Random . 不信心な人はこれを試してみてください 実験 を予測することができることが示されています。 Random の出力は、時間にしておよそ2^16の間にたった2つ(!)の出力値を観測するだけです。今すぐ乱数の出力を予測するには、現代のコンピュータでは1秒もかからない。

まとめ

現在のコードを置き換えます。使用方法 SecureRandom のみです。そうすれば、少なくとも、結果が予測しにくいという保証が少しは得られるでしょう。もしあなたが暗号的に安全なPRNGの特性を求めるなら(あなたの場合はそれが目的です)、次のようにしなければなりません。 SecureRandom だけです。本来の使い方を巧妙に変えようとすると、ほとんどの場合、安全性の低いものができてしまう...。