0

暗号化の目的で Math.random() を使用することは安全ではないことを知っています。乱数を生成するために JavaScript で使用される Math.random() 関数を再構築するサンプル コードが必要です。たとえば、Math.random() によって生成された乱数がある場合、シードが何であったかをどのように把握できますか?

4

1 に答える 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;
}

そう、

  1. 電話Math.random()
  2. 2 53を掛けて整数を取得しnます (明示的に uint64_t を使用する必要があります)。
  3. それを RNG 出力 (の上位ビット) に分割します: 上位 26 ビットn>>27と下位 27 ビットn&((1<<27)-1)
  4. 27 ビットは、最初または 2 番目の RNG 出力のいずれかから取得できます (C と同様に、C++ はここで評価の順序を保証しているとは思いません)。そう...
    • 2 21の可能な下位ビットを反復処理します。
    • RNG を順方向または逆方向に実行して、そこに到達できるかどうかを確認します。
    • あれば、その番号を候補として出力します。

RNG の性質上、複数の候補が存在する可能性があります。

RNG を逆方向に実行することは、読者の課題です (単純に 0x5DEECE66D modulo 2 48の乗法逆数を計算する必要があります)。または、26 ビットの数値を取得して、2 22個の可能な入力をすべて推測することもできます。

于 2013-02-22T23:31:15.970 に答える