【发布时间】:2016-02-06 19:31:21
【问题描述】:
我需要在 PHP 中创建一个可证明公平(确定性和种子)的密码安全 (CS) 随机数生成器。我们正在运行 PHP 5,而 PHP 7 现在并不是一个真正的选择。但是,我找到了 PHP 7 的新 CS 函数的 polyfill,因此我实现了该解决方案 (https://github.com/paragonie/random_compat)。
我认为可以使用 srand() 来播种 random_int(),但现在我不确定是否是这种情况。甚至可以播种 CSPRNG 吗?如果可以播种,输出是否是确定性的(相同的随机结果,给定相同的种子)?
这是我的代码:
require_once($_SERVER['DOCUMENT_ROOT']."/lib/assets/random_compat/lib/random.php");
$seed_a = 8138707157292429635;
$seed_b = 'JuxJ1XLnBKk7gPASR80hJfq5Ey8QWEIc8Bt';
class CSPRNG{
private static $RNGseed = 0;
public function generate_seed_a(){
return random_int(0, PHP_INT_MAX);
}
public function generate_seed_b($length = 35){
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randomString = '';
for($i = 0; $i < $length; $i++){
$randomString .= $characters[random_int(0, strlen($characters) - 1)];
}
return $randomString;
}
public function seed($s = 0) {
if($s == 0){
$this->RNGseed = $this->generate_seed_a();
}else{
$this->RNGseed = $s;
}
srand($this->RNGseed);
}
public function generate_random_integer($min=0, $max=PHP_INT_MAX, $pad_zeros = true){
if($this->RNGseed == 0){
$this->seed();
}
$rnd_num = random_int($min, $max);
if($pad_zeros == true){
$num_digits = strlen((string)$max);
$format_str = "%0".$num_digits."d";
return sprintf($format_str, $rnd_num);
}else{
return $rnd_num;
}
}
public function drawing_numbers($seed_a, $num_of_balls = 6){
$this->seed($seed_a);
$draw_numbers = array();
for($i = 0; $i < $num_of_balls; $i++) {
$number = ($this->generate_random_integer(1, 49));
if(in_array($number, $draw_numbers)){
$i = $i-1;
}else{
array_push($draw_numbers, $number);
}
}
sort($draw_numbers);
return $draw_numbers;
}
}
$CSPRNG= new CSPRNG();
echo '<p>Seed A: '.$seed_a.'</p>';
echo '<p>Seed B: '.$seed_b.'</p>';
$hash = hash('sha1', $seed_a.$seed_b);
echo '<p>Hash: '.$hash.'</p>';
$drawNumbers = $CSPRNG->drawing_numbers($seed_a);
$draw_str = implode("-", $drawNumbers);
echo "<br>Drawing: $draw_str<br>";
运行此代码时,绘图 ($draw_str) 应该在每次运行时都相同,但事实并非如此。
为了证明抽奖是公平的,在中奖号码被抽出并显示之前,先选择一粒种子(种子 A)。还会生成另一个随机数(种子 B)。种子 B 用作盐并与种子 A 结合,结果被散列。该散列在绘图之前显示给用户。他们还将提供源代码,以便在选择中奖号码时显示两个种子。他们可以验证哈希是否匹配,并且一切都被公平地完成了。
【问题讨论】:
-
是的,但这需要 PHP 7。不是一个选项。
-
我可以轻松调整 composer.json 以要求 ^5.6|^7.0 和 random_compat :\
标签: php security random cryptography numbers