web-dev-qa-db-ja.com

bcryptには最大パスワード長がありますか?

今日bcryptをいじってみて、何かに気づきました:

hashpw('testtdsdddddddddddddddddddddddddddddddddddddddddddddddsddddddddddddddddd', salt)
Output: '$2a$15$jQYbLa5m0PIo7eZ6MGCzr.BC17WEAHyTHiwv8oLvyYcg3guP5Zc1y'

hashpw('testtdsdddddddddddddddddddddddddddddddddddddddddddddddsdddddddddddddddddd', salt)
Output: '$2a$15$jQYbLa5m0PIo7eZ6MGCzr.BC17WEAHyTHiwv8oLvyYcg3guP5Zc1y'

Bcryptには最大パスワード長がありますか?

91
d0ctor

はい、bcryptには最大パスワード長があります。 元の記事 には以下が含まれます:

key引数は秘密の暗号化キーで、ユーザーが選択した最大56バイトのパスワードにすることができます(キーがASCII文字列の場合は終端の0バイトを含む)。

したがって、入力パスワードの最大長は55文字であると推測できます(終端のゼロは数えません)。 ASCII文字、注意してください:一般的なUnicode文字は、UTF-8でエンコードされている場合、最大で4バイトを使用できます。視覚的な概念glyphのUnicode文字数は無制限である可能性があります。パスワードをプレーンASCIIに制限すると、多くの心配を省くことができます。

ただし、実際の制限についてはかなりの混乱があります。一部の人々は、「56バイト」の制限には4バイトのソルトが含まれ、51文字の下限につながると信じています。他の人々は、アルゴリズムが内部で18個の32ビットワードとして全体を72バイトとして管理しているため、71文字(または終端が0の文字列を管理していない場合は72文字)になる可能性があると指摘しています。

実際の実装には、実装者が上記のすべてで信じて実施したものに依存する制限があります。すべての適切な実装では、少なくとも50文字を使用できます。それを超えると、サポートは保証されません。 50文字を超えるパスワードをサポートする必要がある場合は、前述のように予備のハッシュステップを追加できます この質問では (もちろん、これは「the」bcryptを計算しなくなったことを意味しますが、ローカルバリアントなので、相互運用性は低下します)。

編集:暗号学者の観点から、articleは最終的な参照です。これは、必ずしも設計者がそれについて考えた方法ではありません。 「元の」実装は最大72バイトを処理できます。形式主義に対するあなたのスタンスによっては、実装は正しく、記事は間違っていると主張するかもしれません。とにかく、これが私のアドバイスが有効である現状の現状です。50文字未満にしておけば、どこでも大丈夫です。 (もちろん、そもそもアルゴリズムに長さの制限がなかった方がよかったでしょう。)

76
Tom Leek

tl; lr:BCryptは56バイトではなく72バイトに制限されています。

バックグラウンド

BCryptは72バイトに制限されています。元の論文では、ヌルターミネータの使用についても触れています。つまり、通常は次のように制限されます。

  • 71文字+ 1バイトのnullターミネーター

ただし、BCrypt 2aリビジョンでは、UTF-8エンコーディングの使用が指定されています(元のホワイトペーパーではASCIIを参照しています)。 UTF-8を使用する場合、1文字は1バイトを意味しません。例:

  • Noëlは4文字ですが、5バイトです(Noe¨l
  • ???? 1文字ですが、4バイト(F09F92A9
  • M̡̢̛̖̗̘̙̜̝̞̟̠̀́̂̃̄̅̆̇̉̊̋̌̍̎̏̐̑̒̓̔̕̚は1文字ですが、74バイト(ヌルターミネーターを含む)

したがって、これにより、レンチが許可されている文字の数に分解されます。

それから55または56はどこから来ますか?

オリジナルのホワイトペーパーでは、キーの最大長は56バイトであると記載されています。

最後に、key引数は秘密の暗号化キーであり、ユーザーが選択した最大56バイトのパスワードにすることができます(キーがASCII文字列の場合は終端の0バイトを含む)。

これは、Blowfishの最大推奨キーサイズ448ビット(448/8 = 56バイト)に基づく誤解でした。 bcryptの派生元であるBlowfish暗号化アルゴリズムの最大キーサイズは448ビットです。 Bruce Schneierの元の1993年の論文から 新しい可変長キーの説明、64ビットブロック暗号(Blowfish)

ブロックサイズは64ビットで、キーは最大448ビットまでの長さにできます。

一方、bcryptアルゴリズムは、最大72バイトのキーをサポートできます(実際にサポートしています)。

  • 71 8ビット文字+ nullターミネーター

72バイトの制限は、Blowfish P-Boxのサイズに由来し、18 DWORD(18 * 4バイト= 72バイト)です。元のbcryptホワイトペーパーから:

Blowfishは64ビットのブロック暗号であり、16ラウンドのFeistelネットワークとして構成されています[14]。 暗号化キーから派生した18個の32ビットサブキー、P1、...、P18を使用します。サブキーは総称してP-Arrayと呼ばれます

正規のOpenBSD実装では、72バイトを超えるキーは切り捨てられます。

つまり、UTF8文字列が72バイトを超える場合、72バイトに切り捨てられます。

警告

  • この切り捨てはnullターミネーターを削除します
  • この切り捨ては文字の途中でも発生します(マルチコードポイント文字の場合)

たとえば、パスワードが「stapler ????」で終わっている場合、BCryptのUTF-8エンコーディングは次のようになります。

    ══╤══╤═══╤═══╤═══╤═══╤═══╤═════╤═════╤═════╗        
... 63│64│ 65│ 66│ 67│ 68│ 69│ 70  │ 71  │ 72  ║ 73   74
    s │ t│ a │ p │ l │ e │ r │ 0xF0│ 0x9F│ 0x92║ 0xA9 \0
    ══╧══╧═══╧═══╧═══╧═══╧═══╧═════╧═════╧═════╝
                                               |
                                            cutoff

正規のOpenBSD実装では、バイトは切り捨てられます文字の途中(無効なutf-8バイトシーケンスが残っていても):

    ══╤══╤═══╤═══╤═══╤═══╤═══╤═════╤═════╤═════╗
... 63│64│ 65│ 66│ 67│ 68│ 69│ 70  │ 71  │ 72  ║
    s │ t│ a │ p │ l │ e │ r │ 0xF0│ 0x9F│ 0x92║
    ══╧══╧═══╧═══╧═══╧═══╧═══╧═════╧═════╧═════╝

最大長を取り除く

近年、パスワードハッシュアルゴリズムに上限を設定しないことをお勧めします。しかし、クライアントがunlimitedパスワードを使用できるようにすることには問題があります。

  • これは、マルチギガバイトのパスワードを送信する誰かによるサービス拒否攻撃をもたらします。

pre-hash SHA2-256のようなユーザーのパスワードが一般的になっているのはこのためです。結果のbase-64エンコードされた文字列、例:

n4bQgYhMfWWaL + qgxVrQFaO/TxsrC4Is0V1sFbDwCgg =

44 ASCII文字(ヌルターミネータ付き45))のみになります。

これは DropBox が採用するアプローチであり、 bcrypt.net に含まれています。

BCrypt.EnhancedHashPassword("correct battery horse staple Noël ???? M̡̢̛̖̗̘̙̜̝̞̟̠̀́̂̃̄̅̆̇̉̊̋̌̍̎̏̐̑̒̓̔̕̚");

これは、高価ハッシュアルゴリズムがサービス拒否を引き起こすことはないことを意味します。

21
Ian Boyd

はい、BCryptの上限は72文字です。これは、Blowfish暗号自体による制限です。これを回避する1つの方法は、最初にSHA-256を使用してから、結果をBCryptすることです。あなたの場合、それは次のようなものになります

hashpw(sha256('pass'), salt)
17
Adi