Coda Haleの記事 "パスワードを安全に保存する方法" は次のように述べています。
bcryptには、Rainbow table攻撃を防ぐための塩が組み込まれています。
彼は この論文 を引用しています。これはOpenBSDのbcrypt
の実装の中で次のように述べています。
OpenBSDはarcfour(arc4random(3))キーストリームから128ビットのbcryptソルトを生成します。これはカーネルがデバイスタイミングから収集したランダムなデータをシードしたものです。
これがどのように機能するのか理解できません。私の塩の概念では:
私がDevise(Railsログインマネージャ)をbcryptと一緒に使っているとき、データベースにsaltカラムがないので、混乱します。塩がランダムで、どこにも保存されていない場合、どのようにしてハッシングプロセスを確実に繰り返すことができますか?
一言で言えば、bcryptはどのようにビルトイン塩を持つことができますか?
これはbcryptです:
ランダムな塩を作ります。 「コスト」要因が事前に設定されています。パスワードを収集してください。
Saltとcostの要素を使ってパスワードから暗号化キーを導出します。よく知られている文字列を暗号化するために使用します。 コスト、salt、、および暗号文を格納します。これら3つの要素は長さがわかっているので、それらを連結して単一のフィールドに格納するのは簡単ですが、後でそれらを分割することもできます。
誰かが認証を試みると、保存されているコストと塩を取得します。入力したパスワード、コスト、およびソルトからキーを導き出します。同じ既知の文字列を暗号化します。生成された暗号テキストが保存されている暗号テキストと一致する場合、パスワードは一致です。
Bcryptは、PBKDF2のようなアルゴリズムに基づくより伝統的な方式と非常によく似た方法で動作します。主な違いは、既知のプレーンテキストを暗号化するための派生キーの使用です。他の方式は(合理的に)鍵導出関数が不可逆的であると仮定し、導出された鍵を直接格納します。
データベースに格納されているbcrypt
の「ハッシュ」は、次のようになります。
$ 2a $ 10 $ vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa
これは実際には「$」で区切られた3つのフィールドです。
2a
は、使用されたbcrypt
アルゴリズムのバージョンを識別します。10
はコスト要因です。 210年 キー導出関数の反復が使用されます(ところで、これでは不十分です。私は12以上のコストを推奨します)。vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa
はソルトと暗号テキストで、修正されたBase-64で連結およびエンコードされています。最初の22文字はsaltの16バイト値にデコードされます。残りの文字は認証のために比較される暗号文です。この例はCoda HaleのRuby実装の ドキュメントから抜粋したものです。
フレーズは次のように表現されるべきだったと思います。
bcryptは生成されたハッシュに組み込まれた塩を持っています Rainbow table攻撃を防ぐために。
bcrypt
ユーティリティ自体は塩のリストを維持しているようには見えません。そうではなく、ソルトはランダムに生成されて関数の出力に追加されるので、後で Java実装のbcrypt
に従って記憶されます)。別の言い方をすれば、bcrypt
によって生成される "ハッシュ"はjustハッシュではありません。むしろ、それはハッシュおよび連結されたソルトです。
これはSpring SecurityのPasswordEncoderインターフェースドキュメントからのものです。
* @param rawPassword the raw password to encode and match
* @param encodedPassword the encoded password from storage to compare with
* @return true if the raw password, after encoding, matches the encoded password from
* storage
*/
boolean matches(CharSequence rawPassword, String encodedPassword);
つまり、次回のログイン時にユーザーが再度入力するrawPasswordと、前回のログイン/登録時にデータベースに保存されているBcryptでエンコードされたパスワードとを照合する必要があります。