web-dev-qa-db-ja.com

誰かがBCryptがハッシュを検証する方法を説明できますか?

パスワードをハッシュするためにC#とBCrypt.Netを使用しています。

例えば:

string salt = BCrypt.Net.BCrypt.GenerateSalt(6);
var hashedPassword = BCrypt.Net.BCrypt.HashPassword("password", salt);

//This evaluates to True. How? I'm not telling it the salt anywhere, nor
//is it a member of a BCrypt instance because there IS NO BCRYPT INSTANCE.
Console.WriteLine(BCrypt.Net.BCrypt.Verify("password", hashedPassword));
Console.WriteLine(hashedPassword);

ソルトをどこにも保存していない場合、BCryptはハッシュを使用してパスワードをどのように検証しますか?私が持っている唯一の考えは、ハッシュの最後にソルトを追加することです。

これは正しい仮定ですか?

30
delete

ソルトをどこにも保存していない場合、BCryptはハッシュを使用してパスワードをどのように確認しますか?

明らかにそれはそのようなことをしていません。塩はどこかに保存する必要があります。

ウィキペディアでパスワード暗号化スキームを調べてみましょう。から http://en.wikipedia.org/wiki/Crypt_(Unix)

関数の出力は単なるハッシュではありません。これは、ソルトをエンコードし、使用されるハッシュアルゴリズムを識別するテキスト文字列です。

または、この件に関する 前の質問 への回答には、 ソースコード へのリンクが含まれていました。 インターネットにソースコードを読んでもらうのではなく、いつでも自分で読むことを選択できます。そうすれば答えが早くなるでしょう。ソースコードの関連セクションは次のとおりです。

    StringBuilder rs = new StringBuilder();
    rs.Append("$2");
    if (minor >= 'a') {
        rs.Append(minor);
    }
    rs.Append('$');
    if (rounds < 10) {
        rs.Append('0');
    }
    rs.Append(rounds);
    rs.Append('$');
    rs.Append(EncodeBase64(saltBytes, saltBytes.Length));
    rs.Append(EncodeBase64(hashed,(bf_crypt_ciphertext.Length * 4) - 1));
    return rs.ToString();

明らかに返される文字列は、バージョン情報、使用されたラウンド数、base64としてエンコードされたソルト、base64としてエンコードされたハッシュです。

26
Eric Lippert

BCryptハッシュstringは次のようになります:

$2a$10$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm
$==$==$======================-------------------------------

どこ

  • 2a:アルゴリズム識別子(BCrypt、UTF8でエンコードされたパスワード、nullで終了)
  • 10:コストファクター(210 = 1,024ラウンド)
  • Ro0CUfOqk6cXEKf3dyaM7O:OpenBSD-Base64でエンコードされたソルト(22文字、16バイト)
  • hSCvnwM9s4wIX9JeLapehKK5YdLxKcm:OpenBSD-Base64でエンコードされたハッシュ(31文字、24バイト)

編集:これらの単語がぴったり合っていることに気づきました。私は共有しなければなりませんでした:

$2a$10$TwentytwocharactersaltThirtyonecharacterspasswordhash
$==$==$======================-------------------------------

BCryptdoesは、16バイトのソルトを使用して24バイトのバイナリハッシュを作成します。バイナリハッシュとソルトは好きなように自由に保存できます。 haveがbase-64で文字列にエンコードすることは何も言いません。

しかしBCryptはOpenBSDに取り組んでいた人たちによって作成されました。 OpenBSDはすでにパスワードファイルのフォーマットを定義しています:

$[HashAlgorithmIdentifier]$[AlgorithmSpecificData]

これは、 "bcrypt仕様"がOpenBSDパスワードファイル形式に容赦なくリンクされていることを意味します。そして、誰かが "bcrypt hash"を作成するときはいつでも、彼らは常にそれをに変換します次の形式のISO-8859-1文字列:

$2a$[Cost]$[Base64Salt][Base64Hash]

いくつかの重要なポイント:

  • 2aはアルゴリズム識別子です
    • 1:MD5
    • 2:どのエンコーディングパスワードが含まれているかについて混乱していた初期のbcrypt(廃止)
    • 2a:パスワードをUTF-8エンコードとして指定する現在のbcrypt
  • Costは、ハッシュを計算するときに使用されるコスト係数です。 「現在の」値は10です。これは、内部キーの設定が1,024ラウンドを通過することを意味します
    • 10:210 = 1,024回の反復
    • 11:211 = 2,048回の反復
    • 12:212 = 4,096回の反復
  • openBSDパスワードファイルで使用されるbase64アルゴリズムは、他のすべての人が使用するBase64エンコーディングと同じではありません。彼らは独自のものを持っています:

    Regular Base64 Alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
        BSD Base64 Alphabet: ./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
    

    したがって、bcryptの実装では、組み込みまたは標準のbase64ライブラリを使用できません。


この知識を身に付ければ、保存されたハッシュに対してパスワードcorrectbatteryhorsestaplerを確認できるようになります。

$2a$12$mACnM5lzNigHMaf7O1py1O3vlf6.BA8k8x3IoJ.Tq3IB/2e7g61Km
85
Ian Boyd