2014-02-11 64 views
2

我正在尋找一個小抽獎,但我希望人們能夠驗證所選號碼是否公平。我知道一些網站使用「Provably Fair」系統來實現這一點,用戶輸入與祕密字符串相結合,然後進行散列以確定中獎號碼。一旦祕密字符串被釋放,參與者就可以使用散列來驗證是否選擇了正確的贏家。這種方法是從sha512哈希生成一個「隨機」數字有效嗎?

從應產生從0-N(N在長度上變化,但是255至多)一個「隨機」號來確定贏家SHA512散列。這是我想了起來:

創建N個長度的數組和插入對可以出現在一個SHA哈希碼字符。例如,如果n爲255,則數組將具有:array('aa','ab','ac'...'fd','fe','ff'...'97','98','99')。基本上它有兩個字符的每個組合使用a-f和0-9。

它會再看看哈希值的前兩個字符,並使用array_search,看是否在陣列中存在對。如果確實如此,它的索引就是挑選的數字,否則它會移到下一對字符並搜索它們。在極少數的情況下,它找不到匹配項,它會不斷地自行散列,並使用返回的新散列來繼續搜索。

$values = array('a','b','c','d','e','f','0','1','2','3','4','5','6','7','8','9'); 
$numbers = array(); 
$ENTRANTS = 50; 
$rand = md5(uniqid(rand(), true)); //This would instead be $secret . $user_input 
$hash = hash('sha512',$rand); 

$values_index = 0; 
$current = $values[$values_index]; 
$options = 0; 
while ($options < $ENTRANTS){ 
    $remaining = ($ENTRANTS - $options > 15)? 16: $ENTRANTS-$options; 
    for ($n=0; $n < $remaining ;$n++){ 
     array_push($numbers, $current . $values[$n]); 
     $options++; 
    } 

    $values_index++; 
    $current = $values[$values_index]; 
} 

$outcomes = array(); 
$winning = null; 
$i = 0; 

while (empty($winning)){ 

    while ($i+1 < 64 && empty($winning)){ 
     $combo = $hash[$i] . $hash[$i+1]; 
     $number = array_search($combo,$numbers); 
     if ($number !== false){ 
      $winning = $number; 
     } 

     $i++; 
    } 

    if (!empty($winning)){ 
     echo "<pre>" . print_r($numbers,true) . "</pre>"; 
     echo $hash . "<br>" . $winning; 
    } 
    else { 
     echo "re-hashing" . "<br>"; 
     $hash = hash("sha512",$hash); 
     $i = 0; 
    } 
} 

這是工作時測試,但我不確定它是否有效地生成一個隨機數。大部分sha512散列中的字符是否均勻且不可預知地分佈?如果您可以看到有關此問題的任何問題或對如何改進提出任何建議,請讓我知道!

+1

交叉張貼到http://crypto.stackexchange.com/questions/14431/is-this-approach-to-generating-a-random-number-from-a-sha512-hash-effective –

+0

此問題似乎因爲它是關於密碼問題而被髮布到Crypo Stack Exchange - http://crypto.stackexchange.com/questions/14431/is-this-approach-to-generating-a-random-number-from -a-SHA512哈希效益 – ChrisF

回答

3

的最佳方式 - 一如既往的密碼 - 是不是推出自己的安全,如果能夠避免它。作爲您的隨機數字發生器rand() is not cryptographically secure(請參閱註釋部分)。對其應用散列不會使這個隨機數生成器安全。實際上,從(一組)不好的RNG製成好的RNG是不可能的。

相反,它是更好的使用openssl_random_pseudo_bytes。有no need to perform any post processing on the bytes you get from that random number generator - 至少不會增加加密強度。

相關問題