ユーザーごとにランダムなトークンを生成する必要のあるアプリケーションを見つけました。生成された各トークンが一意であることは非常に重要です。アプリケーションコードは次のとおりです。
$token = md5(open_ssl_random_pseudo_bytes(64));
正確にわかりませんopen_ssl_random_pseudo_bytes
が機能するか、数値「64」が選択された理由、およびそれらのバイトがMD5ハッシュとどのように連携するか。
それで、このトークンは本当にどれくらいランダムですか?コードが10億回実行された場合、トークンは一意になりますか?
open_ssl_random_pseudo_bytesは 暗号的に安全な疑似乱数ジェネレーター(CSPRNG) です。
簡単に言えば、これは、キー生成に適した、予測不可能な均一に分散されたシーケンスを生成できることを意味します。乱数ジェネレーターの完全な状態がわかっていても、攻撃者は以前に生成されたシーケンスを再作成できず、外部の観測者が将来のシーケンスを予測するために状態を推測することは不可能であるため、予測できないプロパティは重要です。
これは、真夜中を過ぎた秒数からシードを取得し、このシードに基づいて予測可能なシーケンスを生成する乱数ジェネレーターとは対照的です。この場合、攻撃者は、同じシードを使用して数値を生成するように独自のシステムを設定し、トークン値を推測して、それらを独自の悪意のある目的に使用することができます。
64バイトは512ビットのエントロピーを提供します。 MD5は128ビットのハッシュを出力するので、生成されるエントロピーが128を超える利点はありません。コードが10億回実行される場合、出力キースペースが2であるため、常に一意である可能性があります。128 (3.4 * 1038)。 MD5の衝突率は約2です。64 約180億です。
PHPバグ#70014 は最近のことであり、openssl_random_pseudo_bytes()
の信頼性に影響を与えることに注意してください。
私は paragonie/random_compat に取り組んできました。これはrandom_bytes()
をPHP 7からPHP 5に。サポートするフォールバックの1つはopenssl_random_pseudo_bytes()
ですが、/dev/urandom
から直接読み取ることができる場合は、代わりにそれを優先します。
Openssl_random_pseudo_bytesよりも random_bytes を使用することをお勧めします。
マニュアルから(php 7.x以降で利用可能):
random_bytes — Generates cryptographically secure pseudo-random bytes
サンプルコード(マニュアルからも):
<?php
$bytes = random_bytes(5);
var_dump(bin2hex($bytes));
?>
Openssl_random_pseudo_bytes( 71915 )には別のバグがあり、同じプロセスIDで複数回実行すると値が重複する可能性があります。 5.6.24で修正されたようです。