LoginSignup
3
2

More than 3 years have passed since last update.

アルゴリズムを指定しなくてもpassword_verify()で認証できる理由

Posted at

TL; DR

password_hash()で生成されるハッシュ値にハッシュ化に用いたアルゴリズムおよびソルトなどの情報が含まれているため。

各情報が含まれている場所

実際にpassword_hash()の返り値のどこに各情報が含まれているかを見ていきます。

ハッシュ化アルゴリズム

PHP7.3時点では、ハッシュ化のアルゴリズムとしてPASSWORD_BCRYPTPASSWORD_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_DEFAULTPASSWORD_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=以下がスレッド数になります。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2