ユーザーが推測できないトークンを生成するトークンジェネレーターを作成します。トークンジェネレーターはまだ一意です(パスワードのリセットと確認コードに使用されます)。
私はよくこのコードを見ます。それは理にかなっていますか?
_md5(uniqid(Rand(), true));
_
コメントuniqid($prefix, $moreEntopy = true)
に従って
最初の8桁の16進文字= Unixtime、最後の5桁の16進文字=マイクロ秒。
_$prefix
_--パラメーターがどのように処理されるかわかりません。
したがって、$ moreEntopyフラグをtrueに設定しない場合、予測可能な結果が得られます。
質問:しかし、uniqid
を_$moreEntopy
_で使用する場合、md5でハッシュするのは何ですか私たちを買う?より良いですか:
_md5(mt_Rand())
_
edit1:このトークンを一意のインデックスを持つデータベース列に格納するため、列を検出します。興味があるかもしれません/
Rand()はセキュリティハザードであり、セキュリティトークンの生成には決して使用しないでください: Rand()vs mt_Rand() (「静的」画像のような)。しかし、乱数を生成するこれらの方法は、どちらも暗号的に安全ではありません。安全な証明書を生成するには、プラットフォーム、オペレーティングシステム、またはハードウェアモジュールによって提供される [〜#〜] csprng [〜#〜] にアクセスする必要があります。 。
Webアプリケーションでは、安全な秘密の優れたソースは、_/dev/urandom
_などのエントロピープールへのノンブロッキングアクセスです。 PHP 5.3、PHPアプリケーションはopenssl_random_pseudo_bytes()
を使用でき、Opensslライブラリはオペレーティングシステムに基づいて最適なエントロピーソースを選択します、Linuxでは、これはアプリケーションが_/dev/urandom
_を使用することを意味します。スコットのこの コードスニペットはかなり良いです :
_function crypto_Rand_secure($min, $max) {
$range = $max - $min;
if ($range < 0) return $min; // not so random...
$log = log($range, 2);
$bytes = (int) ($log / 8) + 1; // length in bytes
$bits = (int) $log + 1; // length in bits
$filter = (int) (1 << $bits) - 1; // set all lower bits to 1
do {
$rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
$rnd = $rnd & $filter; // discard irrelevant bits
} while ($rnd >= $range);
return $min + $rnd;
}
function getToken($length=32){
$token = "";
$codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
$codeAlphabet.= "0123456789";
for($i=0;$i<$length;$i++){
$token .= $codeAlphabet[crypto_Rand_secure(0,strlen($codeAlphabet))];
}
return $token;
}
_
これは、私が見つけた別の質問のコピーで、この質問の数か月前に尋ねられました。ここに質問と私の答えへのリンクがあります: https://stackoverflow.com/a/13733588/169815 。
私は受け入れられた答えに同意しません。 PHP独自のウェブサイトによると"[uniqid] does not generate cryptographically secure tokens, in fact without being passed any additional parameters the return value is little different from microtime(). If you need to generate cryptographically secure tokens use openssl_random_pseudo_bytes()."
私は答えがこれより明確であるとは思わない、uniqid
は安全ではありません。
質問は古いことは知っていますが、Googleに表示されるので...
他の人が言ったように、Rand()
、mt_Rand()
、またはuniqid()
は、一意性を保証しません... OpenSSLの非推奨機能 を使用するため、openssl_random_pseudo_bytes()
でさえ使用しないでください。
ランダムハッシュ(md5と同じ)の生成に使用する必要があるのは random_bytes() (PHP7で導入)です。 MD5と同じ長さのハッシュを生成するには:
bin2hex(random_bytes(16));
PHP 5.xを使用している場合、 random_compat library を含めることでこの関数を取得できます。
「一意」を定義します。 2つのトークンが同じ値を持つことはできないという意味であれば、ハッシュは十分ではありません-一意性テストで裏付ける必要があります。一意の入力でハッシュアルゴリズムを提供するという事実は、一意の出力を保証するものではありません。
あなたの質問に答えるために、問題は、それ自体でランダムでユニークであることが保証されているジェネレーターを持てないということです。つまり、md5(mt_Rand())
は重複につながる可能性があります。必要なのは、「ランダムに現れる」一意の値です。 uniqidは一意のIDを提供し、Rand()は乱数を付加して推測をさらに困難にし、md5は結果をマスクして推測をさらに困難にします。予想できないことは何もありません。私たちは、彼らが試してさえいられないように、それを非常に難しくする必要があります。
数年前、私は興味深いアイデアに出会いました。
2つのハッシュ値をデータベースに保存します。1つはmd5($ a)で生成され、もう1つはsha($ a)で生成されます。次に、両方の値がcorectである場合はチェックします。ポイントは、攻撃者があなたのmd5()を壊した場合、彼は近い将来あなたのmd5とshaを壊すことができないということです。
問題は次のとおりです。問題に必要なトークン生成でこの概念をどのように使用できますか?
まず、この種の手順の範囲は、特定のデータベースごとに一意のキー/ハッシュ/コードを作成することです。ある瞬間に全世界に固有の何かを作成することは不可能です。そうは言っても、カスタムアルファベットを使用して、プレーンな可視文字列を作成し、作成したコードをデータベース(テーブル)に対してチェックする必要があります。その文字列が一意である場合、md5()
をそれに適用しますが、それは誰またはどのスクリプトでも推測できません。暗号生成の理論を深く掘り下げると、この種のコード生成について多くの説明を見つけることができますが、実際に使用する場合、それほど複雑ではありません。
これは、単純な10桁の一意のコードを生成するために使用するコードです。
_$alphabet = "aA1!bB2@cC3#dD5%eE6^fF7&gG8*hH9(iI0)jJ4-kK=+lL[mM]nN{oO}pP\qQ/rR,sS.tT?uUvV>xX~yY|zZ`wW$";
$code = '';
$alplhaLenght = strlen($alphabet )-1;
for ($i = 1; $i <= 10; $i++) {
$n = Rand(1, $alplhaLenght );
$code .= $alphabet [$n];
}
_
また、生成されたコードをいくつか示しますが、自分で実行して動作を確認できます。
SpQ0T0tyO%
Uwn [MU] [。
D | [ROt + Cd @
O6I | w38TRe
もちろん、より複雑にするために、多くの「改善」を適用できますが、これにmd5()
を適用すると、次のようになります。推測できない」。 :)