パスワードハッシュがどのように機能するかはわかりませんが(後で実装する予定です)、今すぐデータベーススキーマを作成する必要があります。
パスワードを4〜20文字に制限することを考えていますが、ハッシュ文字列を暗号化した後の長さは異なることがわかります。
それでは、これらのパスワードをデータベースに保存する方法は?
更新:単純にハッシュ関数を使用することはパスワードを保存するのに十分強力ではありません。もっと詳しい説明は このスレッドに関するGillesの回答 を読んでください。
パスワードには、BcryptやArgon2iなどの鍵強化ハッシュアルゴリズムを使用してください。たとえば、PHPでは password_hash()関数 を使用します。これはデフォルトでBcryptを使用します。
$hash = password_hash("rasmuslerdorf", PASSWORD_DEFAULT);
結果は次のような60文字の文字列です(ただし、一意のソルトが生成されるため、数字は異なります)。
$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a
SQLデータ型CHAR(60)
を使用して、このBcryptハッシュのエンコーディングを格納します。この関数は16進数の文字列としてエンコードされないので、バイナリで格納するために簡単にunhexすることはできません。
他のハッシュ関数はまだ使用していますが、パスワードの保存には使用していません。そのため、2008年に書かれた以下の元の答えを残します。
それはあなたが使うハッシュアルゴリズムに依存します。ハッシュは、入力に関係なく、常に同じ長さの結果を生成します。バイナリハッシュ結果を一連の16進数としてテキストで表すのが一般的です。または、 UNHEX()
関数を使用して、16進数の文字列を半分にすることもできます。
2015年現在、NIST SHA-256以上の使用を推奨します 相互運用性を必要とするハッシュ関数のアプリケーションには==。しかしNISTは、パスワードを安全に保管するためにこれらの単純なハッシュ関数を使用することをお勧めしません。
より少ないハッシュアルゴリズムには(交換のためではなく、アプリケーションの内部のように)用途がありますが、 解読可能であることが知られています です。
各ハッシュアルゴリズムは常に同じ文字数に評価されるため、実際にはCHAR(ハッシュの長さ)を使用してMySQLのデータ型を定義できます。たとえば、SHA1は常に40文字の16進数を返します。
あなたは塩漬けに関するこのウィキペディアの記事 価値がある を見つけるかもしれません。アイデアは、ハッシュ値をランダム化するためにデータのセットビットを追加することです。誰かがパスワードハッシュへの不正アクセスを取得した場合、これはあなたのパスワードを辞書攻撃から保護します。
固定長文字列として(VARCHAR(n)またはMySQLがそれを呼び出します)。ハッシュは常に固定長で、たとえば12文字です(使用するハッシュアルゴリズムによって異なります)。したがって、20文字のパスワードは12文字のハッシュになり、4文字のパスワードも12文字のハッシュになります。
Argon2 2015パスワードハッシングコンペティションで優勝。 Scrypt 、 bcrypt および PBKDF2 は、現在ではあまり好まれていないと考えられている古いアルゴリズムですが、基本的にはまだ健全です。それでも、今のところ別のアルゴリズムを使用しても構いません。
データベースにパスワードを直接保存しないでください。それを暗号化しないでください。そうでなければ、あなたのサイトが侵害された場合、攻撃者は復号化キーを取得するので、すべてのパスワードを取得することができます。パスワードはハッシュしなければなりません。
パスワードハッシュは、ハッシュテーブルハッシュや暗号化ハッシュとは性質が異なります。パスワードにMD5、SHA-256、SHA-512などの通常の暗号化ハッシュを絶対に使用しないでください。パスワードハッシュアルゴリズムでは、ソルトを使用します。これは一意です(他のユーザーや他のユーザーのデータベースでは使用されません)。攻撃者が一般的なパスワードのハッシュを事前に計算することができないように、ソルトが必要です。ソルトを使用すると、アカウントごとに計算を再開する必要があります。パスワードハッシュアルゴリズムは、本質的に低速です。攻撃者はさまざまなパスワードを試してみる必要があるため、遅さが攻撃者にあなたよりもはるかに大きな悪影響を与えます。詳しくは、 パスワードを安全にハッシュする方法 を参照してください。
パスワードハッシュは4つの情報をエンコードします。
多くのライブラリには、この情報を単一の文字列として便利にパッケージ化するペア関数が含まれています。アルゴリズムインジケータ、硬度インジケータ、およびパスワードを受け取り、ランダムソルトを生成して完全なハッシュ文字列を返します。パスワードと完全なハッシュ文字列を入力として受け取り、パスワードが正しいかどうかを示すブール値を返します。世界標準はありませんが、一般的なエンコーディングは
$アルゴリズム$パラメータ$salt$出力
algorithm
はアルゴリズムの選択をエンコードする数字または短い英数字ストリング、parameters
は印刷可能ストリング、そしてsalt
およびoutput
は=
を終了せずにBase64でエンコードされます。
saltと出力には16バイトで十分です。 (例--- Argon2の推奨 を参照してください。)Base64でエンコードされています。それぞれ21文字です。他の2つの部分はアルゴリズムとパラメータによって異なりますが、20〜40文字が一般的です。これは全部で約82 ASCII文字(CHAR(82)
、そしてUnicodeの必要はありません)です。後でフィールド。
ハッシュをバイナリ形式でエンコードすると、アルゴリズム用に1バイト、硬さ用に1〜4バイト(一部のパラメーターをハードコードした場合)、そしてsaltと出力用にそれぞれ16バイトにハッシュを変換できます。合計37バイト。 40 bytes(BINARY(40)
)とすると、少なくとも2、3バイトの予備のバイトがあるとします。これらは8ビットバイトであり、印刷可能文字ではないことに注意してください。特に、このフィールドにはnullバイトを含めることができます。
ハッシュの長さはパスワードの長さとはまったく関係がないことに注意してください。
それは本当にあなたが使っているハッシュアルゴリズムに依存します。私の記憶が正しければ、パスワードの長さはハッシュの長さとほとんど関係がありません。使用しているハッシュアルゴリズムの仕様を調べ、いくつかのテストを実行し、そのすぐ上で切り捨てます。
ハッシュは一連のビット(アルゴリズムに応じて128ビット、160ビット、256ビットなど)です。 MySQLで許可されている場合(SQL Serverのデータ型はbinary(n)
またはvarbinary(n)
)、列はtext/character-typeではなく、バイナリ型にする必要があります。あなたはまたハッシュを塩漬けにするべきです。塩はテキストまたはバイナリであり、対応する列が必要になります。
前方互換性のためにTEXT
(無制限の文字数を格納する)を使用するべきです。ハッシュアルゴリズム(の必要性)は時間とともに強くなるため、このデータベースフィールドは時間の経過とともにより多くの文字をサポートする必要があります。さらに、移行戦略によっては、同じフィールドに新しいハッシュと古いハッシュを格納する必要がある場合があるため、長さを1種類のハッシュに固定することはお勧めできません。
暗号化された文字列の最大文字列長を見つけ、それをVARCHAR型の文字長として設定することを常にテストしました。レコードの数によっては、データベースのサイズを大きくするのに役立ちます。
md5ではvARCHAR(32)が適切です。 AESを使っている人にはvarbinaryを使ったほうがいいです。