導入
Web開発の現場において、ランダムな文字列の生成は「パスワードのリセット用トークン」「一時的なファイル名」「ユニークなID発行」など、非常に多くの場面で必要とされます。しかし、単にランダムであれば良いというわけではありません。セキュリティが求められる用途において、乱数の生成方法を誤ると予測可能な値が生成され、脆弱性の原因となることがあります。本記事では、実務で安心して使えるランダム文字列生成の基本と、注意すべきポイントを解説します。
基礎知識
PHPで乱数を生成する場合、古くから `rand()` や `mt_rand()` が使われてきました。これらは高速ですが、暗号学的に安全(Cryptographically Secure)ではありません。セキュリティに関わる用途では、PHP 7.0以降で導入された `random_bytes()` や `random_int()` を使用するのが現在の標準です。また、生成したバイナリデータをそのまま使うのではなく、`bin2hex()` や `base64_encode()` を組み合わせて可読性のある文字列に変換するのが一般的です。
実装/解決策
実務では、再利用性を高めるために、使用する文字種や長さを引数で指定できる関数として実装するのが理想的です。また、マルチバイト文字を扱う場合は `mb_substr` を使用しますが、英数字のみの生成であれば `substr` で十分です。処理速度とセキュリティのバランスを考慮し、標準関数を活用した実装を行います。
サンプルプログラム
以下は、暗号論的に安全な乱数生成関数 `random_int` を使用したサンプルコードです。
/
function generateRandomString(int $length = 16): string
{
// 使用する文字のセット(英数字)
$characters = ‘0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’;
$charLength = strlen($characters);
$randomString = ”;
for ($i = 0; $i < $length; $i++) { // random_intは暗号学的に安全な乱数を生成する関数 // 0から文字数-1の範囲でインデックスを安全に取得 $index = random_int(0, $charLength - 1); $randomString .= $characters[$index]; } return $randomString; } // 実行例:20文字のランダム文字列を生成 echo generateRandomString(20); ?>
応用・注意点
現場で注意すべき点は、「用途に応じた乱数生成器の選択」です。
1. セキュリティ用途(トークン、パスワード等): 必ず `random_bytes()` や `random_int()` を使用してください。`mt_rand()` はシード値が推測されるリスクがあるため、避けるべきです。
2. URLやファイル名への利用: 文字列に `+` や `/` が含まれると不都合な場合があります。その場合は `base64_encode` ではなく、`bin2hex` を使うか、特定の文字集合に限定する実装を行ってください。
3. 重複の回避: ランダム文字列をデータベースの主キーなどで使う場合、`uniqid()` や `random_bytes()` を使用しても極稀に衝突する可能性があります。重要なデータには、必ずデータベース側で `UNIQUE` 制約をかけ、衝突時の再試行(リトライ)処理を実装することを忘れないでください。