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

# password_hash

(PHP 5 >= 5.5.0, PHP 7, PHP 8)

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

### 説明

function password_hash(#[\SensitiveParameter]string `$password`, string|int|null `$algo`, array `$options` = []): string

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

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

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

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

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

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

  警告

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

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

  省略した場合のデフォルトは `12` です。この値でもかまいませんが、 ハードウェアの性能に応じて調整すべきです。

`PASSWORD_ARGON2I` と `PASSWORD_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.4.0 | `PASSWORD_BCRYPT` アルゴリズムのデフォルトの `cost` オプションの値が `10` から `12` に引き上げられました。
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
    echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT);
    ?>

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

    $2y$12$4Umg0rCJwMswRw/l.SwHvuQV01coP0eWmGzd61QH2RvAOMANUBGC.

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

    <?php
    $options = [
        // bcrypt のコストを 12 から 13 に増やします
        'cost' => 13,
    ];
    echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options);
    ?>

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

    $2y$13$xeDfQumlmdm0Sco.4qmH1OGfUUmOcuRmfae0dPJhjX1Bq0yYhqbNi

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

このコードは、サーバーをベンチマークして、 ユーザー体験を悪化させることなく、 どの程度のコストに耐えられるかを判断します。 サーバーに負荷をかけすぎない範囲で、 できるだけ高めのコストを設定することをお勧めします。 基準として 11 程度からはじめ、サーバーが十分に高速なら、 できるだけ上げていきましょう。 以下のコードでは、 ストレッチングの時間を 350 ミリ秒以内にすることを狙っています。 対話形式のログインを扱う際の許容時間としては、このあたりが適切でしょう。

    <?php
    $timeTarget = 0.350; // 350 ミリ秒

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

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

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

    Appropriate Cost Found: 13

例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 ミリ秒くらいに収まるくらいが適切です。 先ほどの例のスクリプトは、自分のハードウェア上での適切な bcrypt のコストを判断するための助けとなるでしょう。

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

> - 新しく追加されたアルゴリズムがデフォルトになるまでには、 少なくとも一度は 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() - ASCII 文字でエンコードされたハッシュ値を得る

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open