PHPでBlowfishによるハッシュ値を生成する
「パスワードは平文で保存してはいけない」ということで、PHPにおけるパスワードのハッシュ化について調べてみました。
PHPではBlowfishを推奨しています。
crypt関数を使うとBlowfishによるハッシュ化ができます。
第一引数に平文のパスワードを指定し、第二引数にソルトを指定します。
ソルトとは何でしょうか。次は公式ドキュメントの説明ですが、よく分からないです。
端的に言うと、ソルトとはちょっとした追加データです。これをつけるだけで、ハッシュをクラックするのが劇的に難しくなります。
次は具体的な仕様です。
saltの形式は、"$2a$"か"$2x$"あるいは"$2y$"、2桁のコストパラメータ、"$"、そして文字"./0-9A-Za-z"からなる22文字となります。
この範囲外の文字をsaltに使うと、crypt()は長さゼロの文字列を返します。
2桁のコストパラメータは反復回数の2を底とする対数で、これはBlowfishベースのハッシュアルゴリズムで使います。
この値は04から31までの範囲でなければならず、それ以外の値の場合はcrypt()は失敗します。
5.3.7までのバージョンのPHPでは、saltのプレフィックスとして"$2a$"だけしか使えませんでした。
PHP5.3.7で新たなプレフィックスが導入され、Blowfishの実装にあったセキュリティ上の弱点に対応しました。
セキュリティ修正の対応の詳細については»この文書を参照ください。
簡単にまとめると、PHP5.3.7以降しか使わないのなら"$2a$"ではなく"$2y$"を使うべきだということです。
ソルトはこのルールに従って作ります。このソルトを使えばcrypt関数はBlowfishによるハッシュ化を行います。
私の環境ではPHP5.3.8なので「$2y$」を使うことにします。
例えば
crypt("hirakegoma", "$2y$10$0123456789ABCDEFGHIJKL");
とすると
$2y$10$0123456789ABCDEFGHIJK.2mTpj4MlenV4Ied1RjBP/WBoYzE18z6
というハッシュ値を返します。
次の関数は文字列とコストを与えるとハッシュ値を返します。
$char = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
$salt = "";
for($i = 0; $i < 22; $i++){
$r = mt_rand(0, strlen($char) - 1);
$salt .= substr($char, $r, 1);
}
if($cost < 4){
$cost = 4;
}else if($cost > 31){
$cost = 31;
}
return crypt($str, "$2y$" . sprintf("%02d", $cost) . "$" . $salt);
}
実際に判定に使うときは次のようにします。$inputが入力した文字列、$hashedが正しいパスワードのハッシュ値とします。
「Notice: Undefined variable」が出たときは「$2y$10$GC20〜」を「\$2y\$10\$GC20〜」とするとうまくいきました。
サンプルプログラムをアップしておきます。コストは「10」で固定です。
[ 2014年11月10日 | カテゴリー: PHP | タグ: ハッシュ値 , 暗号 ]
« JavaScriptでPHPのmb_convert_kanaを再現 | iPhone 6を購入 »
コメントを残す