パスワードハッシュのしくみ(後で実装する予定)はわかりませんが、今すぐデータベーススキーマを作成する必要があります。
パスワードを4〜20文字に制限することを考えていますが、暗号化後にハッシュ文字列の長さが異なります。
では、これらのパスワードをデータベースに保存する方法は?
パスワードハッシュのしくみ(後で実装する予定)はわかりませんが、今すぐデータベーススキーマを作成する必要があります。
パスワードを4〜20文字に制限することを考えていますが、暗号化後にハッシュ文字列の長さが異なります。
では、これらのパスワードをデータベースに保存する方法は?
回答:
更新:ハッシュ関数を使用するだけでは、パスワードを保存するには十分ではありません。詳細については、このスレッドで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進数の文字列を半分に減らすことができます。
2015年の時点で、NIST では、相互運用性を必要とするハッシュ関数のアプリケーションにはSHA-256以上を使用することを推奨しています。ただし、NISTでは、パスワードを安全に保管するためにこれらの単純なハッシュ関数を使用することはお勧めしません。
より少ないハッシュアルゴリズムには用途がありますが(アプリケーションの内部ではなく、交換ではありません)、クラック可能であることが知られています。
各ハッシュアルゴリズムは常に同じ数の文字に評価されるため、実際にはCHAR
(ハッシュの長さ)を使用してMySQLのデータ型を定義できます。たとえば、SHA1
常に40文字の16進数を返します。
Argon2は2015年のパスワードハッシュコンテストで優勝しました。Scrypt、bcrypt、およびPBKDF2は古いアルゴリズムであり、現在はあまり好まれていないと考えられていますが、根本的には健全であるため、プラットフォームがまだArgon2をサポートしていない場合は、今のところ別のアルゴリズムを使用してもかまいません。
データベースにパスワードを直接保存しないでください。それも暗号化しないでください。そうしないと、サイトが侵害された場合、攻撃者は復号化キーを取得し、すべてのパスワードを取得できます。パスワードはハッシュ化する必要があります。
パスワードハッシュは、ハッシュテーブルのハッシュまたは暗号化ハッシュは異なる特性を有しています。パスワードにMD5、SHA-256、SHA-512などの通常の暗号化ハッシュを使用しないでください。パスワードハッシュアルゴリズムは、一意のsaltを使用します(他のユーザーや他のユーザーのデータベースでは使用されません)。ソルトは、攻撃者が一般的なパスワードのハッシュを事前に計算できないようにするために必要です。ソルトを使用すると、アカウントごとに計算を再開する必要があります。パスワードハッシュアルゴリズムは本質的に低速です -余裕がある限り低速です。攻撃者は多くの異なるパスワードを試さなければならないので、遅さはあなたよりも攻撃者をはるかに傷つけます。詳細については、「パスワードを安全にハッシュする方法」を参照してください。
パスワードハッシュは4つの情報をエンコードします。
多くのライブラリには、この情報を単一の文字列として便利にパッケージ化するペア関数が含まれています。アルゴリズムインジケーター、硬度インジケーター、パスワードを受け取り、ランダムなソルトを生成して完全なハッシュ文字列を返すものです。パスワードと完全なハッシュ文字列を入力として受け取り、パスワードが正しいかどうかを示すブール値を返すもの。普遍的な標準はありませんが、一般的なエンコーディングは
$ アルゴリズム $ パラメータ $ 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バイトを含めることができます。
ハッシュの長さはパスワードの長さとはまったく関係がないことに注意してください。
固定長文字列として(VARCHAR(n)またはMySQLはそれを呼び出します)。ハッシュは常に固定長(たとえば、12文字)です(使用するハッシュアルゴリズムによって異なります)。したがって、20文字のパスワードは12文字のハッシュに削減され、4文字のパスワードも12文字のハッシュになります。
それは本当にあなたが使っているハッシュアルゴリズムに依存します。私が正しく覚えていれば、パスワードの長さはハッシュの長さとほとんど関係ありません。使用しているハッシュアルゴリズムの仕様を調べ、いくつかのテストを実行し、そのすぐ上で切り捨てます。
ハッシュはビットのシーケンスです(アルゴリズムに応じて、128ビット、160ビット、256ビットなど)。MySQLで許可されている場合(SQL Serverデータ型はbinary(n)
またはvarbinary(n)
)、列はテキスト/文字型ではなくバイナリ型である必要があります。ハッシュも塩漬けにしてください。ソルトはテキストまたはバイナリであり、対応する列が必要になります。
私は常に暗号化された文字列の最大文字列長を見つけるためにテストし、それをVARCHARタイプの文字長として設定しました。取得するレコードの数によっては、データベースのサイズが実際に役立つ場合があります。
md5の場合、vARCHAR(32)が適切です。AESを使用している場合は、varbinaryを使用する方が適切です。