[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()
を利用しています。
ポーカーゲームやカードデッキのシャッフルのような、 偏りがない結果が重要になる用途に合う、 暗号学的にランダムな整数を生成します。
rand()
を使う
<?php // 英数字から $characters = str_split('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'); // ランダムな12文字のパスワードを作る(?) for ($i = 0; $i < 12; $i++) { echo $characters[rand(0, count($characters) - 1)]; }
警告 この関数が生成する値は、暗号学的にセキュアではありません。そのため、これを暗号や、戻り値を推測できないことが必須の値として使っては いけません。
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); }
警告 この関数が生成する値は、暗号学的にセキュアではありません。そのため、これを暗号や、戻り値を推測できないことが必須の値として使っては いけません。
その他、不便な方法
文字種や長さが限られるなど、安全性以前に選ぶ理由のなさそうな方法たちです。
array_rand()
を使うuniqid()
を使うmd5()
などハッシュ関数を使う
まとめ
「ランダムなパスワードを生成する」ことは単に「ランダムな文字列を生成する」こととは別物です。パスワードの生成には単に見かけ上ランダムなだけでなく「暗号学的にセキュア」な方法が必要です。
何が「暗号学的にセキュア」かはマニュアルに記載されています。つまり、マニュアルを読むことが大事です。