Laravel で用意されている認証モジュールを利用する際、ユーザーモデル(User.php)経由で登録されるパスワードのハッシュ方法について調べてみました。
パスワードのハッシュ方式
Laravel 上ではパスワード文字列を bcrypt() のヘルパーでハッシュしています。
このヘルパーの中身を追いかけてみると、要は PHP 標準の password_hash() を使っていることがわかります。
引数の 1 番目はパスワード文字列、2 番目はアルゴリズムですが、アルゴリズムには「PASSWORD_BCRYPT」を利用しています。
実際に、パスワードの入力でそこまで文字数を許容することはないと思いますが、この「PASSWORD_BCRYPT」を指定した場合は、パスワード文字列は 72 文字で切り詰められますので注意が必要です。
password_hash()のハッシュ関数の特徴
これまでに、よく利用されていたハッシュ関数である md5() や sha1() の場合は、1 つの文字列に対して、同じハッシュ文字列が生成されますが、password_hash() の場合は、毎回異なったハッシュ文字列が生成されます。
1 2 3 4 5 6 | $ php -r 'echo password_hash("abcdefg", PASSWORD_BCRYPT) . PHP_EOL;' $2y$10$TCZRVJ878vyN8TdAtwTS4ewscB6uLxFg9Y2tLW8atnpwKhZ8668Si $ php -r 'echo password_hash("abcdefg", PASSWORD_BCRYPT) . PHP_EOL;' $2y$10$XUTeFSiBNPpKe78W5O9f/uo3W9D3Ce212q4buHC2L4Zu5Q/7s5fA2 $ php -r 'echo password_hash("abcdefg", PASSWORD_BCRYPT) . PHP_EOL;' $2y$10$ur3ProIjInKrI.HOhO8xguSmCNV3IDqmpdS9vLJMfS0xLNRXFZEv2 |
ハッシュについてはレインボーテーブルのこととか、説明すると長くなるのでここでは割愛しますが、この password_hash() で生成されたハッシュ文字列と実際の生パスワードが一致しているかどうかは、md5 や sha1 の時と違って、単なる文字列比較ではできません。
この場合、password_verify() 関数で、パスワードがハッシュにマッチするかどうかを確認します。
先ほど発行した最後のハッシュ文字列を例にして、phash.php というファイル名でパスワードのチェックのサンプルを作成してみました。
1 2 3 4 5 6 7 8 9 | <?php $password = 'abcdefg'; $hash = password_hash($password, PASSWORD_BCRYPT); echo 'hash : ' . $hash . PHP_EOL . PHP_EOL; if (password_verify($password, $hash)) { echo 'OK' . PHP_EOL; } else { echo 'NG' . PHP_EOL; } |
実行結果は以下の通りです。
1 2 3 | $ php phash.php hash : $2y$10$EELg6Zm3jnAQ14PPRjP.cuU8UICDGmpyq3B/m9uqJxbGzVRyFQem2 OK |