【PHP】ランダムな文字列、セキュリティ用の文字列を生成する
PHPを使ってランダムな文字列、セキュリティ用の文字列(認証用のトークン)を生成する方法をまとめています。
ランダムな文字列を生成
ランダムな文字列を生成する場合、uniqid関数を使うと良いです。
uniqid関数
uniqid関数は、マイクロ秒単位の現在時刻にもとづいたユニークなIDを生成する関数です。
uniqid();
引数を指定しない場合、「538545fca0b35」のような13文字の文字列が生成されます(16進数の文字(「0~9」と「a~f」)が返されるので、16の13乗通りの文字列が生成される)。
また、引数(例えば「id」)を指定すると、「id538546573c183」のような接頭辞+13文字の文字列が生成されます。
<?php //マイクロ秒単位にもとづいたユニークIDを生成 echo uniqid(); echo uniqid("id"); //接頭辞の付加 ?>
【出力結果】 53854802a145f id53854802a5fe3
【ポイント】
uniqid関数は、マイクロ秒単位の現在時刻にもとづいて文字列を生成するため、完全にランダムな文字列とは言えません(ランダムな文字列というより重複のない(少ない)文字列と言えます)。
重複の少ない文字列と表現したのは、同じマイクロ秒に文字列を生成した場合、同じ文字列が生成されるからです。
そのため一意な文字列やセキュリティ用の文字列を生成したい場合、よりランダムな文字列を生成する必要があります。
よりランダムな文字列を生成
uniqid関数を使ってよりランダムな文字列を生成したい場合、第2引数に「true」を指定し、第1引数にrand関数(乱数を生成する)を指定すると良いです。
第2引数に「true」を指定してエントロピー文字列を付加
uniqid関数の第2引数に「true」を指定すると、線形合同法を使用して生成された文字列が付加され、「53854736d482a9.73269157」のような23文字の文字列が生成されます(「.」(ドット)と数字9文字が追加される)。
<?php //マイクロ秒単位にもとづいた文字列+エントロピー文字列 echo uniqid("", true); ?>
【出力結果】 53854802a60204.26352107
第1引数にrand関数を指定
uniqid関数の第1引数にrand関数を指定すると、さらにランダムな文字列を生成できます。
<?php //rand関数で生成した文字列+マイクロ秒単位にもとづいた文字列+エントロピー文字列 echo uniqid(rand(), true); ?>
出力結果:201087911053854eea3d8731.48796606
セキュリティ用の文字列を生成
さらにmd5関数(32文字の16進数からなるハッシュを返す)を使うと、より推測されにくい文字列を生成することができます。
<?php //rand関数で生成した文字列+マイクロ秒単位にもとづいた文字列+エントロピー文字列 //さらにmd5ハッシュ変換を行う echo md5(uniqid(rand(), true)); ?>
出力結果:a0f208c9b5cff12625cde24454e316a5
さらにランダムなセキュリティ用の文字列を生成
「rand関数で生成した文字列+マイクロ秒単位にもとづいた文字列+エントロピー文字列+md5ハッシュ変換」でほぼ問題ないセキュリティ用の文字列を生成できますが、さらにランダムな文字列を生成したい場合はsha1ハッシュ変換を行います。
<?php //rand関数で生成した文字列+マイクロ秒単位にもとづいた文字列+エントロピー文字列 //さらにsha1ハッシュ変換を行う echo sha1(uniqid(rand(), true)); ?>
出力結果:fa5bca5683d48317414589f61e597d284db5435c
この理由ですが、md5は16進数(「0~9」と「a~f」)の文字を32個生成しますが、パターンを計算すると16の32乗となります。
一方、sha1は16進数(「0~9」と「a~f」)の文字を40個生成するので、パターンを計算すると16の40乗となります。
この理由により、よりランダムな文字列を生成したい場合はmd5ハッシュ変換よりsha1ハッシュ変換の方がよいことになります。
あわせて読んでほしい!
コメント
まだコメントはありません。