web-dev-qa-db-ja.com

PHPでBlowfishを使用してパスワードハッシュを作成および保存する方法

1)crypt()を使用して、パスワードの安全なBlowfishハッシュをどのように作成しますか?

$hash = crypt('somePassword', '$2a$07$nGYCCmhrzjrgdcxjH$');

1a)「$ 2a」の意味は何ですか? Blowfishアルゴリズムを使用する必要があることを示しているだけですか?
1b)「$ 07」の意味は何ですか?より高い値はより安全なハッシュを意味しますか?
1c)「$ nGYCCmhrzjrgdcxjH $」の意味は何ですか?これは使用される塩ですか?これはランダムに生成する必要がありますか?ハードコード?

2)Blowfishハッシュはどのように保存しますか?

echo $hash;
//Output: $2a$07$nGYCCmhrzjrgdcxjH$$$$.xLJMTJxaRa12DnhpAJmKQw.NXXZHgyq

2a)このどの部分をデータベースに保存する必要がありますか?
2b)列(MySQL)にはどのデータ型を使用する必要がありますか?

)ログイン試行をどのように確認する必要がありますか?

27
user479911

Cryptの出力全体を保存する必要があります。分割することはあまり意味がありません。ハッシュ化するパスワードごとに新しいソルトを生成する必要があるためです。 Mattが述べたように固定された非表示のソルトを使用するのは誤りです。ソルトはハッシュごとに異なる必要があります。

詳細は http://www.openwall.com/articles/PHP-Users-Passwords を参照してください-crypt()とは異なり、ランダムパスを生成するため、phpassライブラリを使用することをお勧めします。

13
xyphoid

1a)暗号化の強度-4..31の範囲の要件。参照 http://php.net/manual/en/function.crypt.php

1b)1aを参照

1c)1aを参照してください。 'salt'はランダムであってはなりません。そうでなければ、与えられた入力に対して同じハッシュを再生成することができません-3を参照してください。

2a)厳密に言えば、ハッシュを除くすべて(データベースが侵害された場合)。また、saltをWebサーバーのドキュメントルートの下にあるアクセスできないファイルに保存し、インクルードします。可能な限り厳格な権限で設定してください。理想的には、Webホストサービス(Apacheなど)のみを読み取り、書き込みや実行の権限はありません。厳密に言えば、ハッカーに対する防御力に依存します。塩を保管しないと、生活がより困難になります。データを正しくアルゴリズムに入力する必要がありますが、なぜそれを簡単にするのですか?

2b)VARCHAR(32)は、ハッシュを格納しない場合は、フグの場合は問題ないはずです

3)すでに適切な注入防止コードなどを実行していると仮定します。以下を盲目的にコピーしないでください(そして理想的には、mysql拡張の代わりにPDOを使用してください)。以下は、フグ、SHA-256およびSHA-512に固有のもので、すべてハッシュ内でソルトを返します。他のアルゴリズムの変更が必要になります...

//store this in another file outside web directory and include it
$salt = '$2a$07$somevalidbutrandomchars$'

...

//combine username + password to give algorithm more chars to work with
$password_hash = crypt($valid_username . $valid_password, $salt)

//Anything less than 13 chars is a failure (see manual)
if (strlen($password_hash) < 13 || $password_hash == $salt)
then die('Invalid blowfish result');

//Drop the salt from beginning of the hash result. 
//Note, irrespective of number of chars provided, algorithm will always 
//use the number defined in constant CRYPT_SALT_LENGTH
$trimmed_password_hash = substring($password_hash, CRYPT_SALT_LENGTH);
mysql_query("INSERT INTO `users` (username,p assword_hash) VALUES '$valid_username', '$trimmed_password_hash'");

...

$dbRes = mysql_query("SELECT password_hash FROM `users` WHERE username = '$user_input_username' LIMIT 1");
//re-apply salt to output of database and re-run algorithm testing for match
if (substring($salt, CRYPT_SALT_LENGTH) . mysql_result($dbRes, 0, 'password_hash') ) ===
        crypt($user_input_username . $user_input_password, $salt) ) {
    //... do stuff for validated user
}
0
Matt