PHPのpassword_hashによるパスワードハッシュ化

TL;DR

password_hash() は crypt() よりも簡単に強力なパスワードハッシュを作ることができる、 crypt() のラッパーであり上記互換性を持つ。
今回はこの関数によるハッシュ化の特徴をみていくことにする。

特徴

  • サポートしている暗号化アルゴリズム
    • PASSWORD_DEFAULT → bcrypt アルゴリズムでハッシュかする
    • PASSWORD_BCRYPT → CRYPT_BLOWFISH アルゴリズムでハッシュ化する
    • PASSWORD_ARGON2I → Argon2 を有効にしてコンパイルした場合のみ利用可能
    • PASSWORD_ARGON2ID → Argon2 を有効にしてコンパイルした場合のみ利用可能
  • ソルト
    PHP 7.0.0 以降、ソルトの自動生成が推奨された(より安全に)。
  • cost 2桁のコストパラメータは反復回数(ストレチング)の2を底とする対数で、値は 04 から 31 の範囲にいる必要があり、 それ以外の値の場合は crypt() は失敗。
    つまり、costデフォルトの10は、210 = 1024 回のストレチングになる。
  • ハッシュ値に、ソルトやcost等の値が付いている(ソフト付きパスワードハッシュ値

検証関数

password_verify() を利用し、生のパスワードとパスワードハッシュ値をパラメータにとり、パスワードがマッチするかを検証(true or false)。 * アルゴリズムやソルト値、cost等を知らなくてよい
パスワードハッシュ値にすべて含まれているため、別の場所から取得する必要がない。 * タイミング攻撃に対して安全(のようだ)

動作確認

<?php

$password = "abcdefg1234";

// Blowfishでパスワードハッシュを作る
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);

// 検証
if (password_verify($password, $hashedPassword)) {
    echo "hashedPassword=$hashedPassword" . "\n";
    echo "Hash match ok!\n";
}

?>

まとめ

crypt() では、開発者がアルゴリズム、ランダムなソルト、cost値を指定する必要があり、バグると、脆弱なハッシュ化処理になってしまう可能性はあるが、password_hash() ではcrypt() のラッパーとして、ほとんどの部分を中で自動指定されるようになったことで、より簡単に安全なハッシュ化処理を実現できる。

crypt() ではなく、password_hash() を使うべし。