2

パスワードの生成に使用する乱数 (完全ではない) を取得する必要があります。

私がしていること: 現在、私はSecureRandomでそれらを生成しています。
でオブジェクトを取得しています

SecureRandom sec = SecureRandom.getInstance("SHA1PRNG", "SUN");

そして、このようにシードします

sec.setSeed(seed);

Target : 乱数を作成する (できれば高速な) 方法で、少なくとも SHA1PRNG SecureRandom 実装と同様に暗号学的に安全です。これらは、JRE と Android の異なるバージョンで同じである必要があります。

編集: シードはユーザー入力から生成されます。

問題: 次SecureRandom.getInstance("SHA1PRNG", "SUN");のように失敗します: java.security.NoSuchProviderException: SUN. 省略, "SUN"すると乱数が生成されますが、それらはデフォルト(JRE 7) の数値とは異なります。

質問: どうすれば目標を達成できますか?

あなたはそれが予測可能であることを望んでいません:同じ前提条件が同じ出力をもたらすように予測可能性が必要なので、私は望んでいます。それらが同じでない場合、ユーザーがアプリケーションに期待することを実行するのは不可能 です。

編集: 予測可能とは、1 バイト (または 100) を知っている場合は次を予測できないはずですが、シードを知っている場合は最初 (および他のすべて) を予測できるはずです。たぶん、別の単語が再現可能です。

もっと直感的な方法を知っている人がいたら教えてください!

4

4 に答える 4

1

Java と Android のすべてのバージョンで再現性を保証する太陽のソースから Sha1Prng を分離することになりました。Androidはnioクラスにアクセスできないため、Androidとの互換性を確保するためにいくつかの重要なメソッドを削除する必要がありました...

于 2013-04-09T18:46:48.710 に答える
0

物理的な入力 (ランダム クロック ビット、電気ノイズなど) を使用する RNG を無視すると、開始条件が同じであれば、すべてのソフトウェア RNG は予測可能です。結局のところ、それらは (できれば) 決定論的なコンピューター プログラムです。

予測可能性を防ぐために意図的に物理的な入力を含める (たとえば、コンピュータのクロックをときどきサンプリングするなどして) アルゴリズムがいくつかありますが、それらは (私の知る限り) 例外です。

したがって、同じシードが与えられ、同じ仕様で実装された「従来の」RNG は、同じ「乱数」シーケンスを生成するはずです。(これが、コンピューターの RNG が「疑似乱数ジェネレーター」と呼ばれる理由です。)

RNG が以前に使用されたシードでシードされ、「既知の」数列を再現できるという事実は、RNG の安全性が、何らかの方法でそれをシードできない場合よりも低くすることはありません (ただし、RNG の安全性は、一定間隔で自分自身を再シードする高度なアルゴリズム)。そして、同じシーケンスを何度も再現する能力は、テストで非常に役立つだけでなく、暗号化やその他のセキュリティ アプリケーションで「実際の」用途にも使用できます。(実際、暗号化アルゴリズムは、本質的には、再現可能な乱数ジェネレーターにすぎません。)

于 2013-04-09T16:18:34.297 に答える
0

予測可能にしたい場合、それらはランダムではありません。これは、「安全」であるという「ターゲット」の要件を破り、2 つのサーバー間の単純な共有シークレットに発展します。

一種のランダムに見えますが、素数の特性を使用して予測可能なものを取得できます。ここでは、I (特定の整数) で始まり、最初の素数を追加してから、2 番目の素数によるモジュロを追加して整数のセットを構築します。(実際には、1 番目と 2 番目の数は互いに素である必要があります。つまり、共通の素因数を持たないということです。1 を数えないでください。これを因数と呼ぶ場合に備えて。

加算とモジュロの実行のプロセスを繰り返すと、繰り返し再現できる数値のセットが得られます。それらは、セットの任意のメンバーを取得し、最初の素数を追加し、2 番目でモジュロを実行するという意味で順序付けられます。プライムを使用すると、常に同じ結果が得られます。

最後に、最初の素数が 2 番目の素数に比べて大きい場合、シーケンスは人間が簡単に予測できず、一種のランダムに見えます。

たとえば、1 番目の素数 = 7、2 番目の素数 = 5 (これはどのように機能するかを示していますが、実際には役に立たないことに注意してください)

2 から始めます。7 を足して 9 を取得します。モジュロ 5 で 4 を取得します。4 プラス 7 = 11。モジュロ 5 = 1。

シーケンスは 2、4、1、3、0 で、それが繰り返されます。

次に、ランダムに見える数値の実際の生成について説明します。互いに素な数は 91193 と 65536 です (2 の累乗であるため、2 番目の数を選びました。すべての剰余値は 16 ビットに収まります)。

int first = 91193;
int modByLogicalAnd = 0xFFFF;

int nonRandomNumber = 2345; // Use something else
for (int i = 0; i < 1000 ; ++i) {
    nonRandomNumber += first;
    nonRandomNumber &= modByLogicalAnd;
    // print it here
}

反復ごとに、2 バイトの乱数が生成されます。より大きなランダムな「文字列」が必要な場合は、それらのいくつかをバッファーにパックできます。

そしてそれらは繰り返し可能です。ユーザーは開始点を選択でき、必要な任意の素数 (または、実際には因数として 2 を含まない任意の数) を使用できます。

ところで- 2 の累乗を 2 番目の数値として使用すると、より予測しやすくなります。

于 2013-04-09T15:56:27.423 に答える
0

UUID.randomUUID()を使用してから、 getLeastSignificantBits() と getMostSignificantBits() を使用して long に分割することをお勧めします

于 2013-04-09T15:41:57.767 に答える