Bcryptハッシュパスワードをデータベースに保存するには、どの列タイプ/長さを使用すればよいですか?


318

ハッシュされたパスワード(BCryptを使用)をデータベースに保存したい。これに適したタイプは何ですか?正しい長さはどれですか?パスワードは常にBCryptでハッシュされ、同じ長さですか?

編集

ハッシュの例:

$2a$10$KssILxWNR6k62B7yiX0GAe2Q7wwHlrzhF3LqtVvpyvHZf0MwvNfVu

一部のパスワードをハッシュした後、BCryptは常に60文字のハッシュを生成するようです。

編集2

実装について言及しなかったのは申し訳ありません。私はjBCryptを使用しています


OpenwallのPHPパスワードハッシュフレームワーク(PHPass)もご覧ください。その移植性があり、ユーザーパスワードに対する多くの一般的な攻撃に対して強化されています。フレームワーク(SolarDesigner)を書いた人は、John The Ripperを書いた人と同じで、パスワードハッシュコンテストの審査員を務めています。したがって、彼はパスワードへの攻撃について少し知っています。
jww 2014年

1
誰かがscryptの解決策を探してこれに当てはまる場合:Gumboの答えはscryptにも適用されます。私はMySQLでBINARY(64)を個人的に適用しました。これにより、後でPythonでバイトの等価性をテストすることができました。
Philippe Hebert、2016年

回答:


369

bcryptのモジュラー暗号形式は、

  • $2$$2a$またはハッシュアルゴリズムと形式の$2y$識別
  • コストパラメータを示す2桁の値の後に $
  • 53の文字ベース64符号化された値(それらはアルファベット使用./0- 9A- Za- zとは異なる符号化標準ベース64:からなるアルファベット)
    • 22文字のソルト(事実上、デコードされた132ビットのうち128ビットのみ)
    • 31文字の暗号化された出力(事実上、186ビットのデコードされたビットのうち184ビットのみ)

したがって、全長はそれぞれ59バイトまたは60バイトです。

2a形式を使用するため、60バイトが必要になります。したがって、MySQLのために私が使用することをお勧めしますCHAR(60) BINARYBINARY(60)(参照_binおよびバイナリ照合順序の違いについては、を)。

CHARバイナリセーフではなく、等価性はバイト値だけに依存するのではなく、実際の照合に依存します。最悪の場合Aはと同等に扱われaます。詳細について_bin、およびbinary照合順序を参照してください。


28
注意してください-binary(60)として保存すると、(特に)文字列の等価性が予期しない動作をする可能性があります。.NETでは、これは(fromDataBaseBinary60string、typicalishString、StringComparison.InvariantCulture)String.Equalsを使用することによって克服することができる
JHubbard80

8
列をCHAR(60)CHARACTER SET latin1 COLLATE latin1_binとして定義すると、バイナリ列を必要とせずに正確な文字列比較の利点が得られます。
ベン

2
SQL_Latin1_General_CP1_CS_ASMySQL では@AndreFigueiredo は不明です。知られているのはlatin1_general_csです。
ガンボ

1
私はここでの定義を持っているのが大好きだものを22aと、2yハッシュアルゴリズムや形式の平均。私はいくつかの検索で簡単な答えを見つけることができませんでした。
ジョクル

2
@ネオン問題は、異なるハッシュを等しいと比較する可能性があることです。バイナリ列(または照合順序が正しいVARCHAR)であることを明示的に指定した場合、大文字と小文字を区別しない比較を行う設定を他の場所で変更するリスクはありません。また、意図がより明確になります。これは一般的に良いことです。バイナリデータを格納します。バイナリデータとして保存する必要があります。
モニカの訴訟に資金を提供

52

BcryptハッシュはBINARY(40)列に格納できます。

BINARY(60)は、他の回答が示唆するように、最も簡単で自然な選択ですが、ストレージ効率を最大化したい場合は、ハッシュを無損失で分解することで20バイトを節約できます。GitHub:https : //github.com/ademarre/binary-mcfでこれをより完全に文書化しました

Bcryptハッシュは、モジュラー暗号形式(MCF)と呼ばれる構造に従います。バイナリ MCF(BMCF)は、これらのテキストハッシュ表現をよりコンパクトなバイナリ構造にデコードします。Bcryptの場合、結果のバイナリハッシュは40バイトです。

Gumboは、Bcrypt MCFハッシュの4つのコンポーネントを説明するのに優れています。

$<id>$<cost>$<salt><digest>

BMCFへのデコードは次のようになります。

  1. $<id>$ 3ビットで表すことができます。
  2. <cost>$、04-31、5ビットで表すことができます。これらを1バイトにまとめます。
  3. 22文字のソルトは、128ビットの(非標準の)base-64表現です。Base-64デコードでは16バイトになります。
  4. 31文字のハッシュダイジェストは、base-64で23バイトにデコードできます。
  5. すべてを40バイトにまとめます。 1 + 16 + 23

上記のリンクで詳細を読んだり、GitHubで私のPHP実装を調べたりできます。


49
より長いフィールドのコスト:20バイト×100万+レコード:20 MB、100万レコードに達すると+。非常に複雑なセキュリティおよびエンジニアリング分野で、短いフィールド長を不適切に実装するコスト:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$$$$$$$$$あなたは数学をします。
2016年

6
@Kzqaiは、私が言ったように、より大きな60バイトの列が最も自然な選択ですが、ストレージ効率を追求するためにどの程度積極的に取り組むかはプロジェクトに依存します。たとえば、データベース全体をメモリに収めようとすることは一般的であり、メモリに制約のある環境では、ここに20 MBとそこにさらに20 MBがすぐに追加されます。
Andre D

10
あなたの例は私のポイントにフィードします。---データベースをメモリに配置する場合は、bcryptストレージ列に触れる前に、他のすべての列を最適化します。---他のすべての列を異常な程度に最適化し、bcryptハッシュ列のみが残っている場合は、bcrypt専用の別のメモリギグを取得します。---上記の両方を実行した場合... ...停止し、ぶら下がっている果物の他のすべての列を最適化しておらず、動作するテスト済みの暗号化セキュリティシステムを台無しにし、置き換えます実装が失敗する可能性のある、より複雑な自社開発システムを使用します。
Kzqai 2016年

11
@KzqaiここでBcryptライブラリのセキュリティを弱めるリスクはありません。これは、パスワードチェックの前にストレージから取得されると元に戻されるデータエンコーディングです。これは「自分の暗号を転がしてはいけない」領域ではありません。
Andre D

1
いい説明。:)あなたの説明は素晴らしいアイデアを与えてくれましたが、私はただ安全のために60文字、さらには100文字でいきたいと思っています。素敵な議論も@KzqaiとAndreD
Naveen Kumar V

23

PHP password_hash()PASSWORD_DEFAULTアルゴリズムを使用してbcryptハッシュを生成している場合(これはこの質問を読んでいる人の大部分がそうだと思います)、将来password_hash()、別のアルゴリズムをデフォルトとして使用する可能性があるため、これが原因となる可能性があることに注意してください。ハッシュの長さに影響します(ただし、必ずしも長くなるとは限りません)。

マニュアルページから:

この定数は、新しい強力なアルゴリズムがPHPに追加されると、時間とともに変化するように設計されています。そのため、この識別子を使用した結果の長さは、時間とともに変化する可能性があります。したがって、 60文字を超えて拡張できるデータベース列に結果を格納することをお勧めします(255文字が適切な選択です)。

bcryptを使用すると、10億人のユーザー(つまり、現在Facebookと競合している)が255バイトのパスワードハッシュを保存する場合でも、データは約255 GBにすぎません。パスワードハッシュの保存がアプリケーションのボトルネックになることはほとんどありません。しかし、ストレージスペースが本当にいることをオフのチャンスであるいくつかの理由で問題は、使用することができますPASSWORD_BCRYPT力にpassword_hash()それはデフォルトではありません場合でも、使用bcryptのに。新しいPHPバージョンがリリースされるたびに、bcryptの脆弱性について常に最新情報を入手し、リリースノートを確認してください。デフォルトのアルゴリズムが変更された場合は、その理由を確認し、新しいアルゴリズムを使用するかどうかを情報に基づいて決定することをお勧めします。


20

たとえばMD5ハッシュでできるように、これを保存できる巧妙なトリックはないと思います。

CHAR(60)常に60文字であるので、それをとして保管することをお勧めします。


PHPのドキュメントには、将来のリリースでは列がより多くのデータを保持できるはずであると記載されていますが、
Julian F. Weinert 2015年

16
金メッキする理由はありません。使用しているソフトウェアに60バイトが必要な場合は、60バイトを割り当てます。これを変更するソフトウェアの将来のリリースがある場合、そのリリースが発生したときに心配することができます。機能を変更する更新を自動的にインストールするべきではありません。
タイラークロンプトン2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.