blog.heartyfluid

勉強したることども

[PHP]ランダムなパスワードを生成する(もしくは、こんなパスワード生成は嫌だ)

hackzilla/password-generator を使ってランダムなパスワードを生成する

PHP でランダムなパスワード文字列を生成したいときは、hackzilla/password-generator を使うのがおすすめです。

まず、Composer で導入します。

$ composer require hackzilla/password-generator

そして以下のようにするだけで、英数字から成る10文字のランダムなパスワード文字列が生成できます。

<?php

use Hackzilla\PasswordGenerator\Generator\ComputerPasswordGenerator;

echo (new ComputerPasswordGenerator())->generatePassword();

必要に応じて、パスワードの条件を細かく指定できます。

<?php
declare(strict_types=1);

use Hackzilla\PasswordGenerator\Generator\RequirementPasswordGenerator;

echo (new RequirementPasswordGenerator())
    // 16文字の
    ->setLength(16)
    // 英大文字を1文字以上含み
    ->setMinimumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, 1)
    // 英小文字を1文字以上含み
    ->setMinimumCount(RequirementPasswordGenerator::OPTION_LOWER_CASE, 1)
    // 数字を1文字以上含むような
    ->setMinimumCount(RequirementPasswordGenerator::OPTION_NUMBERS, 1)
    // パスワードを生成
    ->generatePassword();

こんなパスワード生成は嫌だ

ランダムなパスワードを生成するときは、使用する関数について必ずマニュアルで調べましょう。そのような用途に使ってはいけない場合は、マニュアルにその旨書いてあります。

ちなみに、上述の hackzilla/password-generator は内部で random_int() を利用しています。

PHP: random_int - Manual

ポーカーゲームやカードデッキのシャッフルのような、 偏りがない結果が重要になる用途に合う、 暗号学的にランダムな整数を生成します。

rand() を使う

<?php

// 英数字から
$characters = str_split('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');

// ランダムな12文字のパスワードを作る(?)
for ($i = 0; $i < 12; $i++) {
    echo $characters[rand(0, count($characters) - 1)];
}

PHP: rand - Manual

警告 この関数が生成する値は、暗号学的にセキュアではありません。そのため、これを暗号や、戻り値を推測できないことが必須の値として使っては いけません。

mt_rand() を使っても同じことです。

注意: PHP 7.1.0 以降、rand() は、 mt_rand() と同じ乱数生成器を使います。

str_shuffle() を使う

<?php

// 英数字からランダムな12文字のパスワードを作る(?)
for ($i = 0; $i < 12; $i++) {
    echo substr(str_shuffle('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'), 0, 1);
}

PHP: str_shuffle - Manual

警告 この関数が生成する値は、暗号学的にセキュアではありません。そのため、これを暗号や、戻り値を推測できないことが必須の値として使っては いけません。

その他、不便な方法

文字種や長さが限られるなど、安全性以前に選ぶ理由のなさそうな方法たちです。

まとめ

「ランダムなパスワードを生成する」ことは単に「ランダムな文字列を生成する」こととは別物です。パスワードの生成には単に見かけ上ランダムなだけでなく「暗号学的にセキュア」な方法が必要です。

何が「暗号学的にセキュア」かはマニュアルに記載されています。つまり、マニュアルを読むことが大事です。