ハッシュされたパスワードフィールドに使用するデータタイプと長さは?


269

パスワードハッシュのしくみ(後で実装する予定)はわかりませんが、今すぐデータベーススキーマを作成する必要があります。

パスワードを4〜20文字に制限することを考えていますが、暗号化後にハッシュ文字列の長さが異なります。

では、これらのパスワードをデータベースに保存する方法は?


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

2
パスワードに上限を設けないでください。あなたはそれらをハッシュしています、上限にストレージの理由はありません。パスワードハッシュを使用したDoS攻撃が心配な場合は、1000または1024が妥当な上限です。
Iiridayn 2016

なぜパスワードの長さを制限するのですか?少なくともユーザーに100文字のパスワードを作成させる:)
Andrew

4文字はクラックするのが簡単であるため、パスワードのかなり危険な下限です。少なくとも8を使用しますが、14または16の方がはるかに優れています。
quikchange 2016年

これは非常に古い質問で、古い回答です。最新のGillesの回答をご覧ください。
kelalaka

回答:


448

更新:ハッシュ関数を使用するだけでは、パスワードを保存するには十分ではありません。詳細については、このスレッドGillesからの回答を読んでください。

パスワードには、BcryptやArgon2iなどのキー強化ハッシュアルゴリズムを使用します。たとえば、PHPでは、デフォルトでBcryptを使用するpassword_hash()関数を使用します。

$hash = password_hash("rasmuslerdorf", PASSWORD_DEFAULT);

結果は次のような60文字の文字列になります(ただし、一意のソルトを生成するため、数字は異なります)。

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

SQLデータ型CHAR(60)を使用して、Bcryptハッシュのこのエンコードを格納します。この関数は16進数の文字列としてエンコードしないので、バイナリに格納するために16進数を簡単にunhexすることはできません。

他のハッシュ関数にはまだ用途がありますが、パスワードを保存するためのものではないので、2008年に書かれた以下の元の回答を保持します。


使用するハッシュアルゴリズムによって異なります。ハッシュは、入力に関係なく、常に同じ長さの結果を生成します。バイナリハッシュ結果を一連の16進数としてテキストで表すのが一般的です。または、このUNHEX()関数を使用して、16進数の文字列を半分に減らすことができます。

  • MD5は128ビットのハッシュ値を生成します。CHAR(32)またはBINARY(16)を使用できます
  • SHA-1は160ビットのハッシュ値を生成します。CHAR(40)またはBINARY(20)を使用できます
  • SHA-224は、224ビットのハッシュ値を生成します。CHAR(56)またはBINARY(28)を使用できます
  • SHA-256は256ビットのハッシュ値を生成します。CHAR(64)またはBINARY(32)を使用できます
  • SHA-384は、384ビットのハッシュ値を生成します。CHAR(96)またはBINARY(48)を使用できます
  • SHA-512は512ビットのハッシュ値を生成します。CHAR(128)またはBINARY(64)を使用できます
  • BCryptは、実装に依存する448ビットのハッシュ値を生成します。CHAR(56)、CHAR(60)、CHAR(76)、BINARY(56)またはBINARY(60)が必要になる場合があります

2015年の時点で、NIST では、相互運用性を必要とするハッシュ関数のアプリケーションにはSHA-256以上を使用することを推奨しています。ただし、NISTでは、パスワードを安全に保管するためにこれらの単純なハッシュ関数を使用することはお勧めしません。

より少ないハッシュアルゴリズムには用途がありますが(アプリケーションの内部ではなく、交換ではありません)、クラック可能であることが知られています


47
@カバ:ください、ソルトとしてユーザー名を使用しないでください。ユーザーごとにランダムなソルトを生成します。
ビルカーウィン

11
はい、同じ行に格納しない理由はありません。攻撃者がデータベースにアクセスしても、そのソルトに基づいてレインボーテーブルを作成する必要があります。これは、単にパスワードを推測するだけの作業です。
ビルカーウィン、

5
@SgtPooki:ソルトをプレーンテキストで保存するには、別の列が必要です。次に、ユーザーが入力したときに同じソルトを使用してユーザーのパスワードをハッシュし、その結果をテーブルに格納されているハッシュダイジェストと比較できます。
Bill Karwin、2011年

12
同じテーブル(または同じアクセス許可を持つ他の場所)にソルトを格納している場合、ユーザーごとに一意になるため、ソルトとしてユーザー名を使用しない理由はありません。ただし、既知のソルトがあると、既知のソルトがない場合よりもハッシュが暗号的に弱くなります。ソルトは、それも不明な場合にのみ価値を追加します。
フィジーアロン

9
既知の塩と未知の塩の取り決めがわかりません。サイトを実装している場合-パスワードをテストしているログインページ/スクリプト/サービスにソルトが認識されている必要があります。それで、あなたは「未知の」salt支持者です-あなたはログインプロセスのコードが攻撃者に知られていないと思いますか?それ以外の場合- ランダム、一意、ハッシュ化されたパスワードと一緒に格納されているかどうかに関係なく、攻撃者は常にソルトを知っているのですか?
mattstuehler 2013年

13

各ハッシュアルゴリズムは常に同じ数の文字に評価されるため、実際にはCHAR(ハッシュの長さ)を使用してMySQLのデータ型を定義できます。たとえば、SHA1常に40文字の16進数を返します。


1
SHA-1は、パスワードのハッシュには適していません。
Gilles「SO-邪悪なことをやめ

10

常にパスワードハッシュアルゴリズムを使用します:Argon2scryptbcryptまたはPBKDF2

Argon2は2015年のパスワードハッシュコンテストで優勝しました。Scryptbcrypt、およびPBKDF2は古いアルゴリズムであり、現在はあまり好まれていないと考えられていますが、根本的には健全であるため、プラットフォームがまだArgon2をサポートしていない場合は、今のところ別のアルゴリズムを使用してもかまいません。

データベースにパスワードを直接保存しないでください。それも暗号化しないでください。そうしないと、サイトが侵害された場合、攻撃者は復号化キーを取得し、すべてのパスワードを取得できます。パスワードはハッシュ化する必要があります。

パスワードハッシュは、ハッシュテーブルのハッシュまたは暗号化ハッシュは異なる特性を有しています。パスワードにMD5、SHA-256、SHA-512などの通常の暗号化ハッシュを使用しないでください。パスワードハッシュアルゴリズムは、一意のsaltを使用します(他のユーザーや他のユーザーのデータベースでは使用されません)。ソルトは、攻撃者が一般的なパスワードのハッシュを事前に計算できないようにするために必要です。ソルトを使用すると、アカウントごとに計算を再開する必要があります。パスワードハッシュアルゴリズムは本質的に低速です -余裕がある限り低速です。攻撃者は多くの異なるパスワードを試さなければならないので、遅さはあなたよりも攻撃者をはるかに傷つけます。詳細については、「パスワードを安全にハッシュする方法」を参照してください。

パスワードハッシュは4つの情報をエンコードします。

  • 使用されているアルゴリズムのインジケーター。これは俊敏性のために必要です。暗号化の推奨事項は時間とともに変化します。新しいアルゴリズムに移行できる必要があります。
  • 難易度または硬度の指標。この値が大きいほど、ハッシュを計算するために必要な計算が多くなります。これは定数またはパスワード変更機能のグローバル構成値である必要がありますが、コンピューターが高速になるにつれて時間とともに増加するため、各アカウントの値を覚えておく必要があります。一部のアルゴリズムには単一の数値があり、他のアルゴリズムにはより多くのパラメーターがあります(例えば、CPU使用量とRAM使用量を別々に調整するため)。
  • 塩。ソルトはグローバルに一意である必要があるため、アカウントごとに保存する必要があります。ソルトは、パスワードを変更するたびにランダムに生成する必要があります。
  • 適切なハッシュ、つまりハッシュアルゴリズムでの数学的計算の出力。

多くのライブラリには、この情報を単一の文字列として便利にパッケージ化するペア関数が含まれています。アルゴリズムインジケーター、硬度インジケーター、パスワードを受け取り、ランダムなソルトを生成して完全なハッシュ文字列を返すものです。パスワードと完全なハッシュ文字列を入力として受け取り、パスワードが正しいかどうかを示すブール値を返すもの。普遍的な標準はありませんが、一般的なエンコーディングは

$ アルゴリズム $ パラメータ $ salt $ 出力

ここalgorithm数またはアルゴリズムの選択をコードする短い英数字の文字列であり、parameters印刷可能な文字列であり、saltそしてoutput終了せずにBase64でエンコードされています=

ソルトと出力には16バイトで十分です。(Argon2の推奨事項などを参照してください。)Base64でエンコードされ、それぞれ21文字です。他の2つの部分はアルゴリズムとパラメーターによって異なりますが、20〜40文字が一般的です。これは合計で約82のASCII文字(でCHAR(82)、Unicodeは必要ありません)です。後でフィールドを拡大するのが難しいと思われる場合は、安全マージンを追加する必要があります。

ハッシュをバイナリ形式でエンコードする場合、アルゴリズムの場合は1バイト、硬度(一部のパラメーターをハードコードする場合)の場合は1〜4バイト、ソルトと出力の場合はそれぞれ16バイトにハッシュできます。 、合計37バイト。セイ40バイトBINARY(40)少なくとも予備バイトのカップルを持っているが)。これらは8ビットのバイトであり、印刷可能な文字ではないことに注意してください。特に、フィールドにnullバイトを含めることができます。

ハッシュの長さはパスワードの長さとはまったく関係がないことに注意してください。


9

あなたは価値のある塩漬けに関するこのウィキペディアの記事を見つけるかもしれません。アイデアは、ハッシュ値をランダム化するためにデータのセットビットを追加することです。これにより、誰かがパスワードハッシュに不正アクセスした場合に、辞書攻撃からパスワードを保護できます。


2
それは確かに非常に価値があります(+1)が、質問には答えません!(-1)
ビルカーウィン、

3
はい、間違いなく関連するこのような状況(1)中
TREB

7

固定長文字列として(VARCHAR(n)またはMySQLはそれを呼び出します)。ハッシュは常に固定長(たとえば、12文字)です(使用するハッシュアルゴリズムによって異なります)。したがって、20文字のパスワードは12文字のハッシュに削減され、4文字のパスワードも12文字のハッシュになります。


3
「しかし、MySQLはそれを呼び出す」-MYSQLはCHARと呼ぶ。このタイプは固定長値用です。したがって、CHARはVARCHARよりも優れたタイプだと思います。
t298712383

4

TEXT上位互換性のために(無制限の文字数を格納する)を使用する必要があります。ハッシュアルゴリズム(必要)は時間とともに強くなるため、このデータベースフィールドは時間とともにより多くの文字をサポートする必要があります。また、移行戦略によっては、新しいハッシュと古いハッシュを同じフィールドに格納する必要がある場合があるため、長さを1つのタイプのハッシュに固定することはお勧めしません。


3

それは本当にあなたが使っているハッシュアルゴリズムに依存します。私が正しく覚えていれば、パスワードの長さはハッシュの長さとほとんど関係ありません。使用しているハッシュアルゴリズムの仕様を調べ、いくつかのテストを実行し、そのすぐ上で切り捨てます。


3

ハッシュはビットのシーケンスです(アルゴリズムに応じて、128ビット、160ビット、256ビットなど)。MySQLで許可されている場合(SQL Serverデータ型はbinary(n)またはvarbinary(n))、列はテキスト/文字型ではなくバイナリ型である必要があります。ハッシュも塩漬けにしてください。ソルトはテキストまたはバイナリであり、対応する列が必要になります。


正義はここで完全に正しい-MySQLはこれらを数値として格納し、この列での検索を文字列照合よりもはるかに効率的にしますが、ソルトはソルトデータの横にあるデータベースに格納しないでください-ソルトが提供する安全性を排除します。
Tony Maro

6
塩は秘密ではありません唯一の秘密はパスワードです。すべての新しいパスワードが新しいソルトを取得することを確認してください。ユーザーがパスワードを変更するたびに、システムはそのパスワードに対して新しいソルトを生成する必要があります。ソルトは長く暗号化されていないPRNGから生成された16バイトなどのランダムである必要があります。
yfeldblum 2011

1
@TonyMaroパスワードレベルの文字列がSQLレベルで一致するかどうかはわかりません。つまり、データベースでパスワードを検索するのではなく、SQLでなく、ユーザー名に基づいてユーザーを取得し、コード内でパスワードを比較します。
Bart

1

私は常に暗号化された文字列の最大文字列長を見つけるためにテストし、それをVARCHARタイプの文字長として設定しました。取得するレコードの数によっては、データベースのサイズが実際に役立つ場合があります。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.