暗号化の目的で Math.random() を使用することは安全ではないことを知っています。乱数を生成するために JavaScript で使用される Math.random() 関数を再構築するサンプル コードが必要です。たとえば、Math.random() によって生成された乱数がある場合、シードが何であったかをどのように把握できますか?
質問する
678 次
1 に答える
2
ソースを見てください。この場合、mozilla/js/src/jsmath.cpp にあります:
static const uint64_t RNG_MULTIPLIER = 0x5DEECE66DLL;
static const uint64_t RNG_ADDEND = 0xBLL;
static const uint64_t RNG_MASK = (1LL << 48) - 1;
static const double RNG_DSCALE = double(1LL << 53);
/*
* Math.random() support, lifted from java.util.Random.java.
*/
...
extern uint64_t random_next(uint64_t *rngState, int bits)
{
uint64_t nextstate = *rngState * RNG_MULTIPLIER;
nextstate += RNG_ADDEND;
nextstate &= RNG_MASK;
*rngState = nextstate;
return nextstate >> (48 - bits);
}
static inline double random_nextDouble(JSContext *cx)
{
uint64_t *rng = &cx->compartment->rngState;
return double((random_next(rng, 26) << 27) + random_next(rng, 27)) / RNG_DSCALE;
}
そう、
- 電話
Math.random()
- 2 53を掛けて整数を取得し
n
ます (明示的に uint64_t を使用する必要があります)。 - それを RNG 出力 (の上位ビット) に分割します: 上位 26 ビット
n>>27
と下位 27 ビットn&((1<<27)-1)
。 - 27 ビットは、最初または 2 番目の RNG 出力のいずれかから取得できます (C と同様に、C++ はここで評価の順序を保証しているとは思いません)。そう...
- 2 21の可能な下位ビットを反復処理します。
- RNG を順方向または逆方向に実行して、そこに到達できるかどうかを確認します。
- あれば、その番号を候補として出力します。
RNG の性質上、複数の候補が存在する可能性があります。
RNG を逆方向に実行することは、読者の課題です (単純に 0x5DEECE66D modulo 2 48の乗法逆数を計算する必要があります)。または、26 ビットの数値を取得して、2 22個の可能な入力をすべて推測することもできます。
于 2013-02-22T23:31:15.970 に答える