2016-07-06 24 views
5

我需要在更長的敘述中(多個用戶可以同時在不同的機器上執行相同的動作)爲多個句子生成唯一的ID。正在生成並連接3個Math.random()的值比1個Math.random()的值更隨機?

我認爲做new Date().getTime()(也許是一個串聯username),但是,作爲標識的是在一個循環,而迭代的判決產生,我發現創建副本(如代可在同一毫秒發生)。

var random1 = Math.floor((Math.random() * 10000) + 1).toString(36); 
var random2 = Math.floor((Math.random() * 10000) + 1); 
var random3 = Math.floor((Math.random() * 10000) + 1); 
var id = random1 + random2 + random3; 
// generates things like: 
// 1h754278042 
// 58o83798349 
// 3ls28055962 

它發生在我雖然(當然,誰的人沒有思考獨特/隨機/密碼多少的問題),這也許是連接三個隨機數ISN」:

所以我目前正在與玩弄再隨機一個隨機數?

產生並連接的3 Math.random()值比1 Math.random()的值更隨機?

這個答案(https://security.stackexchange.com/a/124003)規定:

如果隨機發生器產生真正的隨機數據那麼就不會 問題。

但我不知道如何適用於Math.random()的用法。

編輯:

方案是基於Web,而不是出於安全客戶端,只是爲了確保每個句子在數據庫中唯一的ID。

編輯:

我最終實現:

function guid() { 
    function s4() { 
    return Math.floor((1 + Math.random()) * 0x10000) 
     .toString(16) 
     .substring(1); 
    } 
    return s4() + s4() + '-' + s4() + '-' + s4() + '-' + 
    s4() + '-' + s4() + s4() + s4(); 
} 

var id = guid(); 

來源:https://stackoverflow.com/a/105074/1063287

也看到這個問題的答案評論:

其實,RFC允許從隨機創建的UUID號碼。你只需要旋轉幾個比特就可以將其識別爲 等等。參見4.4節。用於從真正 創建UUID隨機或僞隨機數的算法:rfc-archive.org/getrfc.php?rfc=4122

+0

這是否在網絡上運行客戶端,並且您是否計劃將其用於安全性? – Liam

+0

在網絡上是客戶端,而不是安全 - 只是爲了確保每個句子在數據庫中都有唯一的ID。 – user1063287

+7

@ user1063287'Math。random()'的目的不是提供唯一性 –

回答

0

這很複雜。

由於的具體方式您正在使用隨機數發生器,第一個字符串可能是相同的,而第二個或第三個字符串是不同的。這意味着你可以產生更多獨特的字符串,而不需要通過一次性撥打Math.random()。更多獨特的字符串意味着更少的碰撞,這就是你所要的目標。

要確認這一點,只需將大量這些字符串轉儲到文件中,然後對它們進行排序,並查看第二個和第三個值是否總是隨第一個值更改,或者它們是否可以獨立更改(您需要添加分隔符到輸出看看)。

這是PRNG狀態隱藏方式的一種假象;並在幾個附加後它將停止工作。它應該(不保證!)經過這麼多的迭代後,你將無法輕鬆測試它,所以不要試圖通過經驗來解決它。

如果你有一個非常原始的生成算法,那麼你可能會發現,每當random1等於X,則random2總是等於Y和random3將始終是等於z;所以如果你在X處發生碰撞,那麼隱含的Y和Z也會相互碰撞,所以他們不會提供幫助。

但是大多數PRNG(以及代碼的結構,因爲每次調用只取得10000個不同的值),它們的狀態比它在單個調用中顯示的狀態大得多。這意味着即使random1是X,random2random3仍然是完全不可預測的,並且由於它們的存在使得碰撞不太可能。

然而,當你到達random100時,你應該開始看到你可以猜測它將基於所有其他randomX的值,並且它不會使字符串更獨特。

然後,整個問題就會從種子質量和狀態大小的兔子洞中跑下來。從根本上來說,隨機數發生器非常弱,只能產生少至40億個獨特的字符串,在實際情況下可能會少得多。 random()函數並不是爲了解決GUID問題,所以存在一個風險就是它會失敗。

1

的Math.random()返回與正號,大於或等於0,但小於1,隨機選擇或僞一個數字值隨機地在該範圍內大致均勻分佈,使用實現相關算法或策略。

這裏是V8的實現:

uint32_t V8::Random() { 

// Random number generator using George Marsaglia's MWC algorithm. 
static uint32_t hi = 0; 
static uint32_t lo = 0; 

// Initialize seed using the system random(). If one of the seeds 
// should ever become zero again, or if random() returns zero, we 
// avoid getting stuck with zero bits in hi or lo by reinitializing 
// them on demand. 
if (hi == 0) hi = random(); 
if (lo == 0) lo = random(); 

// Mix the bits. 
hi = 36969 * (hi & 0xFFFF) + (hi >> 16); 
lo = 18273 * (lo & 0xFFFF) + (lo >> 16); 
return (hi << 16) + (lo & 0xFFFF); 
} 

來源:http://dl.packetstormsecurity.net/papers/general/Google_Chrome_3.0_Beta_Math.random_vulnerability.pdf

換句話說3個的隨機值ANE不超過1

+0

這個實現去年是[fixed](http://v8project.blogspot.com/2015/12/theres-mathrandom-and-then-theres.html)。 – sh1

+0

請具體說明,如果你必須把它放在引號中,給出「(更多)隨機」的定義。 – Bergi

2

您通過均勻串聯3修改的東西更多 '隨機'分佈隨機字符串是一個更大的可能值範圍。分佈仍然是統一的,所以它不再是「隨機的」,但它的確顯着降低了碰撞風險。可能的值的數量將爲36^12或4.7383813e + 18。

通過連接12個基數 - 36位數字(0-9,A-Z)可以獲得相同的效果。

+0

實際上OP選擇連接字符串的算法並不統一,因爲他沒有確保長度不變...... – Bergi

相關問題