TL; DR
password_hash()
で生成されるハッシュ値にハッシュ化に用いたアルゴリズムおよびソルトなどの情報が含まれているため。
各情報が含まれている場所
実際にpassword_hash()
の返り値のどこに各情報が含まれているかを見ていきます。
ハッシュ化アルゴリズム
PHP7.3時点では、ハッシュ化のアルゴリズムとしてPASSWORD_BCRYPT
とPASSWORD_ARGON2I
の2種類を使用することができます。
PASSWORD_ARGON2I
はPHP7.2で追加されました。
# PASSWORD_BCRYPT
echo password_hash( 'password', PASSWORD_BCRYPT );
$2y$10$Fn1sh4A7w0G7XYEVu7TDf.lDAJGLwKRwvZBel3FJ9f0cMjLCOgDs6
# PASSWORD_ARGON2I
echo password_hash( 'password', PASSWORD_ARGON2I );
$argon2i$v=19$m=1024,t=2,p=2$YWJHdzJUL001Nlp2NEw0Nw$mCjdG6lbo0ccc77QRBzlhEhHJJVIVLBILoWh/5zmQSs
# PASSWORD_DEFAULT
echo password_hash( 'password', PASSWORD_DEFAULT );
$2y$10$TCtG3d5te5yhSMAgJwLAou7xrleJEdj.QV8a3uoRltOUknmzUmWYe
$2y
から始まるのがPASSWORD_BCRYPT
で$argon2i
から始まるのがPASSWORD_BCRYPT
になります。
サポートするオプションが違うので他にも明らかに違いますが。
また、PASSWORD_DEFAULT
の返り値を見てください。
$2y
で始まるのでPASSWORD_DEFAULT
はPASSWORD_BCRYPT
と同一のアルゴリズムであることが分かります。
ソース上は、ext/standard/php_password.hで定義されています。
PASSWORD_BCRYPTのオプション
コスト(cost)
利用するアルゴリズムのコストを指定することができます。
指定されたコストにより計算された回数だけストレッチング処理が行われます。
コストの詳細について気になる方は、以下の記事をご参照ください。
https://qiita.com/hayashi-ay/items/361f67f18b023e674d15
# コストを未指定
echo password_hash( 'password', PASSWORD_BCRYPT );
$2y$10$Fn1sh4A7w0G7XYEVu7TDf.lDAJGLwKRwvZBel3FJ9f0cMjLCOgDs6
# コストを指定
$options = array();
$options['cost'] = 14;
echo password_hash( 'password', PASSWORD_BCRYPT, $options );
$2y$14$HpW15mXL7M0Iwrzg4XCnuOWU/7NGxqZjnrlPMcUJEIhRs8IfDrLBW
$2y
以下の数字がコストを表します。
未指定の場合$10
、つまり10がコストのデフォルト値となることが分かります。
ソルト(salt)
パスワードのハッシュに使うソルトを手動で設定することができます。
ソルトの長さは22文字であり、それより長いものを指定すると22文字に切り詰められます。
※PHP7.0.0以降ではソルト・オプションは非推奨になりました。
# ソルトを未指定
echo password_hash( 'password', PASSWORD_BCRYPT );
$2y$10$Fn1sh4A7w0G7XYEVu7TDf.lDAJGLwKRwvZBel3FJ9f0cMjLCOgDs6
# ソルトを指定
$options = array();
$options['salt'] = 'xxxxxxxxxxxxxxxxxxxxxx'
echo password_hash( 'password', PASSWORD_BCRYPT, $options );
$2y$10$xxxxxxxxxxxxxxxxxxxxxuOd9YtxiLKHM/l98x//sqUV1V2XTZEZ.
コスト$10
の後に続く$
以下がソルトになります。
未指定の場合はランダムに生成された値になります。
PASSWORD_ARGON2Iのオプション
メモリの最大値(memory_cost)
# メモリの最大値を未指定
echo password_hash( 'password', PASSWORD_ARGON2I );
$argon2i$v=19$m=1024,t=2,p=2$YWJHdzJUL001Nlp2NEw0Nw$mCjdG6lbo0ccc77QRBzlhEhHJJVIVLBILoWh/5zmQSs
# メモリの最大値を指定
$options = array();
$options['memory_cost'] = 10000;
echo password_hash( 'password', PASSWORD_ARGON2I, $options );
$argon2i$v=19$m=10000,t=2,p=2$L2VJSkxNSHJIV094ek05SQ$s3yRsqTM33df55rS2GHIykFAcVRm1UuNHfpdsS0cNwo
$m=
以下がメモリの最大値になります。
時間の最大値(time_cost)
# 時間の最大値を未指定
echo password_hash( 'password', PASSWORD_ARGON2I );
$argon2i$v=19$m=1024,t=2,p=2$YWJHdzJUL001Nlp2NEw0Nw$mCjdG6lbo0ccc77QRBzlhEhHJJVIVLBILoWh/5zmQSs
# 時間の最大値を指定
$options = array();
$options['time_cost'] = 4;
echo password_hash( 'password', PASSWORD_ARGON2I, $options );
$argon2i$v=19$m=1024,t=4,p=2$c0FHME9vekJhNmxuR2ZTLw$OcuEesY2gnKNHgMVd7hUPMBYCbqYIAHEGT0dJ5TKtu4
$t=
以下が時間の最大値になります。
スレッド数(threads)
# スレッド数を未指定
echo password_hash( 'password', PASSWORD_ARGON2I );
$argon2i$v=19$m=1024,t=2,p=2$YWJHdzJUL001Nlp2NEw0Nw$mCjdG6lbo0ccc77QRBzlhEhHJJVIVLBILoWh/5zmQSs
# スレッド数を指定
$options = array();
$options['threads'] = 4;
echo password_hash( 'password', PASSWORD_ARGON2I, $options );
$argon2i$v=19$m=1024,t=2,p=4$R2ZxekRVTnBsSks2NXllTQ$nBeQdObmceth+zcZkaqHzNhIFseAW0stEiNk430wHng
$p=
以下がスレッド数になります。