より高速に、推測困難な一意なIDを生成する方法
PHP7以降では等確率に選ばれるランダムな値を得る関数に、random_int() と random_bytes() があります。
random_int()は数字、random_bytes()はバイト文字列です。
これを使用すると一意なキーの生成は次のようになります。
sha1(random_bytes(10));
PHP5以前や下位互換を考える時には、一意なキーを生成するのに、uniqid()があります。
これは現在時間をマイクロ秒単位にしたものを使用しています。
つまりランダムというより、重複のない値となります。
PHPのuniqid()のマニュアルページにも、「戻り値の一意性を保証するものではありません。」とあります。
戻り値は、『 4a4f513eb71b1 』のような半角英数字の13文字です。16進数文字なので、「0から9 aからf」です。
第一引数にはプレフィックス、第二引数には追加のエントロピーの使用の有無を渡すことができます。
第二引数はデフォルトは false になっていますが、trueにするとドット『 . 』と数字9文字が追加され、文字数が23文字になります。
『 4a4f5caadd40c2.19903592 』このような値です。
半角英数字のみにするにはsha1ハッシュ変換します。
sha1(uniqid(null, true))
sha1の戻り値は、40文字の半角英数字(0から9 aからf)です。
セッションクッキーなどの推測されては困るようなトークンに使用する場合には、いくつかの関数を組み合わせます。
例えば、プレフィックスにも uniqid() をつける方法があります。
sha1(uniqid(uniqid(), true))
これよりほかの乱数エントロピーを組み合わせたほうがより推測困難になります。
sha1(uniqid(dechex(rand()), true))
より高速にするためには、rand()よりもmt_rand()を使用します。
sha1(uniqid(dechex(mt_rand()), true))
これで推測困難なIDを高速に生成することができます。
PHP7.4以降ではuniqid()の第一引数にmt_rand()などをそのまま指定すると次のようなエラーが出ます。
uniqid() expects parameter 1 to be string, int given
第一引数はstring型が宣言されているのでmt_rand()だとint型となりエラーが出ます。
このため10進数を16進数に変換するdechex()を使用しています。
サンプルコード
echo sha1(uniqid(dechex(mt_rand()), true));
とすると
46e1e7d630f1ff4d2ba8d9c295758df5
と返ります。
注意点
md5は衝突性(コリジョン)があることが証明されていて、セキュリティホールとなることが潜在的に存在します。
このためsha1を使用するほうがいいです。
md5は半角英数文字で構成されるため0から9、aからzの10+26文字=36文字と思っている人がいますが、これは間違いです。
md5は16進数32桁なので0から9、aからfの10+6文字=16文字
「16の32乗」通りです。
(2進数にすると128ビットになります)
同様にsha1は16進数40桁なので「16の40乗」通りです。
(2進数にすると160ビットになります)
第2引数にtrue を指定すると、sha1 ダイジェストは 20 バイト長のバイナリ形式の値を返します。
これはバイナリなので画面に表示させると文字化けのようになります。
関連記事
- PHPでwebサーバー(apache/nginx)の実行ユーザー・グループを確認する方法
- リクエストヘッダーやリクエストボディーなどを取得する方法
- 負荷が高いときには503エラーを返す方法
- サイトの更新情報をPINGサーバに送信する方法
- PHPでロードアベレージを表示させる方法
- PHPでTwitterのツイートをする/ツイート一覧を取得する/検索する(API v1.1)
- インクルードパスを設定する方法
- オブジェクト(Object)を配列(Array)に変換する方法
- PHPでgzip圧縮形式(gz圧縮)のファイルを読み書きする方法
- PHPでfacebook投稿時に公開範囲を指定する方法
- PHPで複数の画像をfacebookに投稿する方法
- PHPでfacebookのフィード(ウォール)に投稿する方法
- PHPでのfacebookアプリの認証処理(APIを使うユーザー認証)
- MySQL関数のまとめ
- MySQLサーバに接続できるかどうかを確認する
- ディレクトリ内のファイルのパーミッションを一括で変更する
- POSTでアップロードできるファイルサイズの制限を変更する方法
- 暗号化・複合化を行う ブロック暗号
- date型やdatetime型と年月日時分秒への変換
- 関数・メソッドの存在を調べる方法
- PHPでTwitterのbotを作る方法 ツイートをする/ツイート一覧を取得する(API v1)
- strtotimeの指定
- PHPでHTMLメールを送る方法
- ディレクトリセパレータを短く定義する DIRECTORY_SEPARATOR
- モザイク画像を作る方法
- HTML内のアクセス解析タグを除去する方法
- HTMLのTABLEタグを簡単にCSVファイルに変換する方法
- 画像表示のときに指定サイズにリサイズする(画像の拡大縮小)
- テキストを可逆的な暗号化する Crypt_Blowfish
- PHPでwhois検索をする Net_Whois
- よく使うヘッダー関数のまとめ
- キャリア・世代を判別する
- mb_send_mailでCCやBCCを指定する 表示名を指定する
- 画像ファイルを指定容量ぎりぎりに圧縮する
- 指定したHTTPヘッダーが送信済みあるいは送信予定に含まれているか
- DOCUMENT ROOTを得る $_SERVER["DOCUMENT_ROOT"]は使えない!
- マルチバイト文字列(日本語文字)を一文字づつ取り出す
- ファイルを削除する/フォルダを削除する
- ファイルを読み込む/ファイルに書き込む
- ディレクトリ内のファイル一覧を取得する
- quoted-printable文字列の変換
スポンサーリンク