とあるWeb制作会社
ワイ「パイセン、こないだ頼まれとったパスワード保存処理完成しましたで」
先輩「おお、ありがとうな」
先輩「・・・何やこれ」
ワイ「言われた通りハッシュ化しといて、saltと一緒に保存しとりまっせ」
ワイ「検証する時は、入力値とsaltくっつけてハッシュ化して比較すればいけまっせ」
先輩「何で令和に、しかもLaravel8つこてる時に生PHP書いとるんやお前」
先輩「お前が今言うた事、LaravelのHash::make
と Hash::check
でできるから、置き換えや」
ワイ「便利でんなー」
ワイ「ほな、 Hash::make
でハッシュ化されたパスワードとsaltを受け取って保存しとく、みたいな感じでっか?」
先輩「saltは気にせんでええよ。 Hash::make
はハッシュ化されたパスワードしか返さんし、 Hash::check
する時にsaltは要らん」
ワイ「は? そしたらどうやって正しいパスワードかどうか検証するんでっか」
ワイ「気になって夜しか眠られへん」
(ワイ記法思ったより疲れたのでここまでで終わりです。 @Yametaro 先生へのリスペクトが高まりますね)
結論
Hash::makeの返り値に、入力値のハッシュ値だけでなくsaltやハッシュ化アルゴリズム等ハッシュ化に必要な情報が全て含めてある。よって、別の形で保存する必要は無い。
Hash::makeとHash::checkはPHP組み込み関数 password_hash
と password_verify
をラップして使いやすくしてくれたもの。便利だから使いまくろう。
調べたこと
Hash::make
と Hash::check
の中身を見る所から始めます。
ソースコードを読むと、パスワードのハッシュ化と検証にはPHPの組み込み関数 password_hash
と password_verify
を使っているようでした。
そして password_hash
の説明には以下のようにあります。
使ったアルゴリズムやコスト、そしてソルトもハッシュの一部として返されます。 つまり、ハッシュを検証するために必要な情報は、すべてそこに含まれているということです。 そのため、password_verify() でハッシュを検証するときに、 ソルトやアルゴリズムの情報を別に保存する必要はありません。
どのような形式で他の情報を付与しているのか? 検証時にどのように確認するのか? まで見ようと思うとCのコードを読む必要がありそうなのですが、当方Cはからきしであるため、ここまでにします。
https://github.com/php/php-src/blob/master/ext/standard/password.c
5/6 追記
@yu-ichiro さんにコメント(ありがとうございます!)頂いた所、この部分はPHPの仕様というより、ハッシュ化アルゴリズムの都合のようです。
パスワードのハッシュ値以外の情報をどのように付与しているのかについて、Laravel標準で使われているハッシュ化アルゴリズムBcryptの仕様がWikipediaにまとめられていました。
LaravelではBcryptの他にArgon2も使う事ができるので、Argon2の仕様も簡単にググってみましたが日本語記事が見つけられませんでした。こちらの仕様書は英語で難しかったので諦めましたが、気になる方がいれば読んでみても良いかと思います。
その他参考にしたドキュメントなど