2014-02-11 40 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 - 至少不会增加加密强度。

相关问题