password_hash

パスワードハッシュを作る

説明

string password_hash(#[\SensitiveParameter]string $password, stringintnull $algo, array $options = [])

password_hash は、 強力な一方向ハッシュアルゴリズムを使って、 新しいパスワードハッシュを作ります。

現在、以下のアルゴリズムに対応しています。

  • PASSWORD_DEFAULT - bcrypt アルゴリズムを使います (PHP 5.5.0 の時点でのデフォルトです)。 新しくてより強力なアルゴリズムが PHP に追加されれば、 この定数もそれにあわせて変わっていきます。 そのため、これを指定したときの結果の長さは、変わる可能性があります。 したがって、結果をデータベースに格納するときにはカラム幅を 60 文字以上にできるようなカラムを使うことをお勧めします (255 文字くらいが適切でしょう)。
  • PASSWORD_BCRYPT - CRYPT_BLOWFISH アルゴリズムを使ってハッシュを作ります。これは標準の crypt 互換のハッシュで、識別子 "$2y$" を使った場合の結果を作ります。 その結果は、常に 60 文字の文字列になります。失敗した場合に false を返します。
  • PASSWORD_ARGON2I - Argon2i ハッシュアルゴリズムを使って ハッシュを作ります。このアルゴリズムは、 PHP が Argon2 のサポートを有効にしてコンパイルした場合のみ利用できます。
  • PASSWORD_ARGON2ID - Argon2id ハッシュアルゴリズムを使って ハッシュを作ります。このアルゴリズムは、 PHP が Argon2 のサポートを有効にしてコンパイルした場合のみ利用できます。

PASSWORD_BCRYPT がサポートするオプション:

  • salt (string) - パスワードのハッシュに使うソルトを手動で設定します。 これは、自動生成されたソルトを上書きすることに注意しましょう。

    省略した場合は、パスワードをハッシュするたびに password_hash がランダムなソルトを自動生成します。これは意図したとおりの操作モードです。

    警告

    このソルト・オプションは 非推奨になっています。 このオプションは指定せずに、デフォルトで生成されるソルトを使うことを推奨します。 PHP 8.0.0 以降は、この値を明示的に指定しても無視されます。

  • cost (int) - 利用するアルゴリズムのコストを表します。 値の例については crypt のページを参照ください。

    省略した場合のデフォルトは 10 です。この値でもかまいませんが、 ハードウェアの性能が許すならもう少し高くすることもできます。

PASSWORD_ARGON2IPASSWORD_ARGON2ID が サポートするオプション

  • memory_cost (int) - Argon2 ハッシュを計算するのに 使われるメモリの最大値(キロバイト単位)。 デフォルトは PASSWORD_ARGON2_DEFAULT_MEMORY_COST です。

  • time_cost (int) - Argon2 ハッシュを計算するのに 使って良い時間の最大値。 デフォルトは PASSWORD_ARGON2_DEFAULT_TIME_COST です。

  • threads (int) - Argon2 ハッシュを計算するのに使う スレッド数。 デフォルトは PASSWORD_ARGON2_DEFAULT_THREADS です。

    警告

    PHP が libargon2 を使う場合にのみ利用可能です。 libsodium の実装では利用できません。

パラメータ

password

ユーザーのパスワード。

警告

PASSWORD_BCRYPT をアルゴリズムに指定すると、 password が最大 72 バイトまでに切り詰められます。

algo

パスワードのハッシュに使うアルゴリズムを表す パスワードアルゴリズム定数

options

オプションを含む連想配列。各アルゴリズムがサポートするオプションについては、 パスワードアルゴリズム定数 のページを参照ください。

省略した場合は、ランダムな salt を生成してデフォルトのコストを使います。

戻り値

ハッシュしたパスワードを返します。

使ったアルゴリズムやコスト、そしてソルトもハッシュの一部として返されます。 つまり、ハッシュを検証するために必要な情報は、すべてそこに含まれているということです。 そのため、password_verify でハッシュを検証するときに、 ソルトやアルゴリズムの情報を別に保存する必要はありません。

変更履歴

バージョン 説明
8.0.0 password_hash は、失敗時に false を返さなくなりました。 代わりに、パスワードハッシュのアルゴリズムが有効でなかった場合は ValueError がスローされるようになりました。 また、パスワードハッシュの作成が不明なエラーで失敗した場合は、 Error がスローされるようになっています。
8.0.0 引数 algo は、 nullable になりました。
7.4.0 algo パラメータは string を期待するようになりました。 しかし、後方互換性のために int も未だ受け入れています。
7.4.0 sodium 拡張モジュールが、 Argon2 パスワードの実装の代替を提供するようになりました。
7.3.0 PASSWORD_ARGON2ID を使った、 Argon2id パスワードのサポートが追加されました。
7.2.0 PASSWORD_ARGON2I を使った、 Argon2i パスワードのサポートが追加されました。

例1 password_hash の例

<?php
/**
 * デフォルトのアルゴリズムを使ってパスワードをハッシュします。
 * 現時点でのデフォルトは BCRYPT で、その結果は 60 文字になります。
 *
 * デフォルトは、今後変わる可能性があることに注意しましょう。結果が
 * 60 文字以上になっても対応できるようにしておきましょう (255 あたりが適切です)
 */
echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT);
?>

上の例の出力は、 たとえば以下のようになります。

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

例2 password_hash で、コストを手動で設定する例

<?php
/**
 * この例では、BCRYPT のコストをデフォルトより上げて、12 にします。
 * また、アルゴリズムを BCRYPT に変えたことにも注目しましょう。結果は常に 60 文字になります。
 */
$options = [
    'cost' => 12,
];
echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options);
?>

上の例の出力は、 たとえば以下のようになります。

$2y$12$QjSH496pcT5CEbzjD/vtVeH03tfHKFy36d4J0Ltp3lRtee9HDxY3K

例3 password_hash で、適切なコストを探す例

<?php
/**
 * このコードは、サーバーをベンチマークして、どの程度のコストに耐えられるかを判断します。
 * サーバーに負荷をかけすぎない範囲で、できるだけ高めのコストを設定したいものです。
 * 基準として 10 程度からはじめ、サーバーが十分に高速なら、できるだけ上げていきましょう。
 * 以下のコードでは、ストレッチングの時間を 350 ミリ秒以内にすることを狙っています。
 * 対話形式のログインを扱う際の許容時間としては、このあたりが適切でしょう。
 */
$timeTarget = 0.350; // 350 ミリ秒

$cost = 10;
do {
    $cost++;
    $start = microtime(true);
    password_hash("test", PASSWORD_BCRYPT, ["cost" => $cost]);
    $end = microtime(true);
} while (($end - $start) < $timeTarget);

echo "Appropriate Cost Found: " . $cost;
?>

上の例の出力は、 たとえば以下のようになります。

Appropriate Cost Found: 12

例4 Argon2i を使った password_hash の例

<?php
echo 'Argon2i hash: ' . password_hash('rasmuslerdorf', PASSWORD_ARGON2I);
?>

上の例の出力は、 たとえば以下のようになります。

Argon2i hash: $argon2i$v=19$m=1024,t=2,p=2$YzJBSzV4TUhkMzc3d3laeg$zqU/1IN0/AogfP4cmSJI1vc8lpXRW9/S0sYY2i2jHT0

注意

警告

この関数で使うソルトを自前で設定するのはお勧めしません。 ソルトを省略すれば、安全なソルトをこの関数が自動的に作ってくれます。

先述のとおり、PHP 7.0 で salt オプションを指定すると、 非推奨の警告が発生します。ソルトを手動で設定する仕組みは、PHP 8.0 で削除されました。

注意:

実際にサーバー上でこの関数をテストして、コストパラメータの適切な設定値を調整することをお勧めします。 対話型のシステムなら、関数の実行時間が 350 ミリ秒くらいに収まるくらいが適切です。 先ほどの例のスクリプトは、自分のハードウェア上での適切なコストを判断するための助けとなるでしょう。

注意: この関数がサポートするアルゴリズムの更新 (あるいはデフォルトのアルゴリズムの変更) は、必ず次の手順にのっとって行われます。

  • 新しく追加されたアルゴリズムがデフォルトになるまでには、 少なくとも一度は PHP のフルリリースを経ること。 つまり、たとえば、新しいアルゴリズムが 7.5.5 で追加されたとすると、 そのアルゴリズムがデフォルトになるのは早くても 7.7 以降ということになります (7.6 は、最初のフルリリースだからです)。 しかし、もし別のアルゴリズムが 7.6.0 で追加されたとすると、 そのアルゴリズムも 7.7.0 の時点でデフォルトになる資格を得ます。
  • デフォルトを変更できるのはフルリリース (7.3.0 や 8.0.0 など) のときだけで、リビジョンリリースでは変更できない。 唯一の例外は、現在のデフォルトにセキュリティ上の致命的な欠陥が発覚した場合の緊急リリースです。

参考

  • password_verify
  • password_needs_rehash
  • crypt
  • sodium_crypto_pwhash_str