PHPでBlowfishによるハッシュ値を生成する

Pocket

「パスワードは平文で保存してはいけない」ということで、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
というハッシュ値を返します。

次の関数は文字列とコストを与えるとハッシュ値を返します。

function crypt_blowfish($str, $cost){
  $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が正しいパスワードのハッシュ値とします。

if(crypt($input, $hashed) == $hashed){
  //処理
}

「Notice: Undefined variable」が出たときは「$2y$10$GC20〜」を「\$2y\$10\$GC20〜」とするとうまくいきました。

サンプルプログラムをアップしておきます。コストは「10」で固定です。

Blowfishによるハッシュ値

[ 2014年11月10日 | カテゴリー: PHP | タグ: ]

« | »

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

送信してください。


タグ

カテゴリー

最近の投稿

最近のコメント

固定ページ

アーカイブ

stabucky

写真

メタ情報