22

パスワードの保存に関する Jeff Atwood の投稿を読んだ後、私は BCrypt.net に出くわしました。これにより、Thomas Ptacek が BCrypt を使用してパスワードを保存することを勧めました。最終的に、この BCrypt の C# 実装にたどり着きました

上記の最後のリンクのコメントで、誰かが「GenerateSalt(30) には時間がかかるのに、GenerateSalt(31) にはまったく時間がかからないように見えるのはなぜですか?」と尋ねました。

BCrypt.HashPassword(password, BCrypt.GenerateSalt(31)) を実行したところ、0 ミリ秒で結果が得られました。

BCrypt.HashPassword("password", BCrypt.GenerateSalt(30)) を 5 分以上実行していますが、まだ結果がありません。

パスワード ハッシュ (またはBCrypt の場合は元に戻せない暗号化)を作成するために、ランダムに生成された 30 文字のソルトはおそらく何年も必要ないでしょう。編集私はコードを少し読むべきでした.logRoundsはソルトの長さとは何の関係もありません. ありがとうアーロノート。

では、GenerateSalt(31) がほぼ瞬時に値を返すのはなぜですか (GenerateSalt(30) の約 2 倍の時間がかかるのに)。

アップデート

ここに修正があります:

private byte[] CryptRaw(byte[] password, byte[] salt, int logRounds) {
    // ... snip ...
    uint rounds = 1U << logRounds;
    // ... snip
}
4

2 に答える 2

25

バグがここにあると思われます:

private byte[] CryptRaw(byte[] password, byte[] salt, int logRounds) {
    // ... snip ...
    int rounds = 1 << logRounds;
    // ... snip
}

に 31 を指定するとlogRounds、それは 2^32 として計算され、これは に収まらず、intオーバーフローするため、ハッシュは実際には ... えーと、ゼロパスで行われます。著者はuint代わりに使用する必要がありました。簡単に直せます!


これについてもコメントしたかった:

パスワード ハッシュを作成するために、ランダムに生成された 30 文字のソルトはおそらく必要ないでしょう...

logRoundsパラメータはソルト内の文字/バイト数を参照しないことに注意してください。これは常に 16 です。これは、ハッシュが計算に使用するパス数の対数ベースを参照します。言い換えれば、これはムーアの法則で bcrypt をスケーリングする方法であり、コンピューターが既存のハッシュをクラックするのに十分なほど高速になった場合、関数の計算コストが数桁高くなります。

于 2010-02-08T15:11:55.437 に答える
10

If hashing with GenerateSalt(31) returns almost instantly, that's a bug. You should report that upstream (I have, for jBCrypt). :-)

By default, the log-rounds is 10. This means that (if I remember correctly), 1024 rounds is used. Each time you increment the log-rounds, the number of rounds is doubled.

At 30 log-rounds, you're doing 1073741824 rounds. That rightfully takes a long time. At 31 log-rounds, 2147483648 rounds should be being done, but I suspect that the particular implementation you're using overflows instead. :-(

于 2010-02-08T15:02:35.410 に答える