karashi39とはいったい

夢と希望と明日と正義を讃える

password_hashを使ってみた(PHP)

uzullaさん曰く、「MD5なんて使ってる場合じゃない!」(YAPC2014にて)
なんという昔の話をしてるんだという感じもしますが、試してみました。

まずはこんなコードを実行

<?php

echo "test1\n";
echo password_hash('karashi39', PASSWORD_DEFAULT);
echo "\ntest2\n";
echo password_hash('karashi39', PASSWORD_DEFAULT);
echo "\n";

結果は、下記の通り。

$ php test.php
test1
$2y$10$.lIJjeDpOVKEBQjYyC8gle4O.5aBcfhESGEfRvbifBISsAZO7pE8K
test2
$2y$10$Yzzwpf8z2R7UJS3FJAc6GutURq62.sV.luXA1lY3RLecjA.6xkZWC

初心者な私は、あれ?って思いました。
同じ文字列を暗号化してるのに、違う結果がでてくる・・

typoがあったのか?
オプションがおかしいのか?
PHPがこわれているのか?

などということを一瞬思いましたが、
あせらず、次のようなコードを実行してみました。

<?php

if (password_verify('karashi39', '$2y$10$.lIJjeDpOVKEBQjYyC8gle4O.5aBcfhESGEfRvbifBISsAZO7pE8K')){
    echo "hash1 is ok.\n";
} else{
    echo "hash1 is not ok.\n";
}

if (password_verify('karashi39', '$2y$10$Yzzwpf8z2R7UJS3FJAc6GutURq62.sV.luXA1lY3RLecjA.6xkZWC')){
    echo "hash2 is ok.\n";
} else{
    echo "hash2 is not ok.\n";
}

if (password_verify('karashi39', '$2y$10$Yzzwpf8z2R7UJS3FJAc6GutURq62.sV.luXA1lY3RLecjA.6xkZWc')){
    echo "hash3 is ok.\n";
} else{
    echo "hash3 is not ok.\n";
}

1、2個目のhash値は、さっき生成したもの。
3個目のhash値は、2個目の最後の文字を大文字から小文字に変更したもの。
実行結果は、こう。

$ php test2.php
hash1 is ok.
hash2 is ok.
hash3 is not ok.

ちゃんと、karashi39という文字列から生成したhash値だけ、OKが出るようになってる!

というわけで、password_hashは、元の文字列から一意ではないhash値を生成し、
password_verifyは、第一引数(?)がhash値の元の文字列であるかをチェックすると理解。
また一つ、勉強になりました。

なにげに冷静にさっと対処したように書きましたが、
同じhash値が出ないことに30分くらいググりまくって調べました。初心者感丸出し。

なお、password_hash関数のいいところはこれだけではなさそうなので、
確認が取れ次第また記事を書きます。