我知道使用Math.random()进行加密是不安全的。我需要一个重构JavaScript中使用的Math.random()函数的示例代码来生成随机数。例如,如果我有一个由Math.random()生成的随机数,我怎么能弄清楚种子是什么?
答案 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;
}
所以,
Math.random()
n
(你想明确使用uint64_t)n>>27
和后27位n&((1<<27)-1)
。由于RNG的性质,可能有多个候选人。
向后运行RNG是读者的练习(您只需要计算0x5DEECE66D模2 48 的乘法逆)。或者,您可以采用26位数字并猜测所有2 22 可能的输入。