如何重建Math.random()的种子?

时间:2013-02-22 22:46:16

标签: javascript random cryptography

我知道使用Math.random()进行加密是不安全的。我需要一个重构JavaScript中使用的Math.random()函数的示例代码来生成随机数。例如,如果我有一个由Math.random()生成的随机数,我怎么能弄清楚种子是什么?

1 个答案:

答案 0 :(得分: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位可以来自 第一个或第二个RNG输出(如C,我不认为C ++在这里对评估顺序提供任何保证)。所以...
    • 迭代2 21 可能的低位。
    • 看看你是否可以通过向后运行RNG forwards 来到达那里。
    • 如果是,请输出该号码作为候选人。
  5. 由于RNG的性质,可能有多个候选人。

    向后运行RNG是读者的练习(您只需要计算0x5DEECE66D模2 48 的乘法逆)。或者,您可以采用26位数字并猜测所有2 22 可能的输入。