2013-02-22 37 views
0

我知道使用Math.random()進行加密的目的是不安全的。我需要重構JavaScript中用於生成隨機數的Math.random()函數的示例代碼。例如,如果我有一個由Math.random()生成的隨機數,我怎麼才能知道種子是什麼?如何重建Math.random()的種子?

+0

猜測隨機種子,直到它工作 – 2013-02-22 22:47:34

+1

單個數字並不意味着一個特定的種子值。 – 2013-02-22 22:48:15

+1

你有什麼方法可以知道PRNG被調用了多少次? – TML 2013-02-22 22:48:27

回答

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 得到一個整數n(你要明確使用uint64_t中)
  3. 將其分割成RNG輸出(的高位):頂部26位n>>27和底部27位n&((1<<27)-1)
  4. 27位可以從或者第一個或第二個RNG輸出(比如C,我不認爲C++在這裏對評估順序有任何保證)。所以...
    • 對可能的較低位進行遍歷2 。
    • 看看您是否可以通過向後運行RNG轉發來實現此目的。
    • 如果是,輸出該數字作爲候選人。

由於RNG的性質,具有多個候選可以是一種可能性。

向後運行RNG是一個練習給讀者(您只需計算0x5DEECE66D的模乘2 )的乘法逆。或者,您可以使用26位數字並猜測所有可能的輸入。

+0

謝謝,顯然,它與Java中的nextDouble()相同。 – Wise 2013-02-25 17:50:51