大随机数生成

问题描述:

我需要一个大的(比如说,128位大)的随机数生成器在PHP中。我正在考虑将此数字作为十六进制存储在字符串中。大随机数生成

请注意,这是一个登录系统,提到需要一个“随机”数字,所以我猜我真的需要它“足够随机”(因为我知道伪随机是从未真正随机)。

我正在考虑的算法是一次生成第一个十六进制数字,然后将它连接在一起。就像这样:

$random = ''; 
for ($i = 0; $i < 32; ++$i) { 
    $digit = rand(0, 15); 
    $random .= ($digit < 10 ? $digit : ($digit - 10 + 'a')); 
} 
return $random; 

我能相信这个函数返回良好的伪随机数还是我的东西我真的不应该搞乱?

尝试:

for ($str = '', $i = 0; $i < $len; $i++) { 
    $str .= dechex(mt_rand(0, 15)); 
} 

我经常看到的只是在做类似的登录系统,此处理:

$salt = "big string of random stuff"; // you can generate this once like above 
$token = md5($salt . time()); // this will be your "unique" number 

MD5哈希值可以有冲突,但是这是非常有效和非常简单。

+0

为什么不直接替换$ salt by rand()?难道它不是随机的吗?哎呀,可能更随机。 – luiscubal 2010-09-11 20:53:46

+0

这是真的,但如果你想这样做,但使用rand()会否定你对比期望散列的能力。例如。在密码的情况下,你经常会用盐对用户的密码进行散列 - 然后,因为你大概是唯一知道盐的人,那么你可以比较你记录在该用户数据库中的散列与“期望的散列“,你可以验证它是正确的。 – julio 2010-09-16 16:37:12

几年前我问过这个问题,从那以后,我对这个主题的认识有所提高。

首先,我提到我想要一个登录系统的随机数字。登录系统是安全机制。 这意味着登录系统依赖的任何随机数发生器应该是加密安全

PHP的randmt_rand不是加密安全的。

在这些情况下,最好是安全而不是遗憾。有专门设计为安全的随机数发生器,特别是openssl_random_pseudo_bytes(不幸的是,这种随机数发生器并不总是可用的 - 您必须启用OpenSSL扩展才能使其工作)。在* NIX系统(如Linux)上,字节也从/dev/urandomcan be used中读取。

不幸的是(对于这个问题),这两种方法都返回二进制数据而不是十六进制数据。幸运的是,PHP已经有一个函数来解决这个问题,bin2hex,它适用于任何长度的字符串。

因此,这里的代码会是什么样子:

function generate_secure_random_hex_string($length) { 
    // $length should be an even, non-negative number. 

    // Because each byte is represented as two hex digits, we'll need the binary 
    // string to be half as long as the hex string. 
    $binary_length = $length/2; 

    // First, we'll generate the random binary string. 
    $random_result = openssl_random_pseudo_bytes($binary_length, $cstrong); 

    if (!$cstrong) { 
     // The result is not cryptographically secure. Abort. 
     // die() is just a placeholder. 
     // There might be better ways to handle this error. 
     die(); 
    } 

    //Convert the result to hexadecimal 
    return bin2hex($random_result); 
} 

// Example: 
echo generate_secure_random_hex_string(32); 

由于PHP 5.3:

function getRandomHex($num_bytes=4) { 
    return bin2hex(openssl_random_pseudo_bytes($num_bytes)); 
} 

为了您的128位例如:

$rand128 = getRandomHex(16);