产生在PHP加密安全随机数产生在PHP加密安全随机数(Generate cryptographica

2019-05-13 18:43发布

PHP的rand()函数没有给出很好的随机数。 于是,我开始使用mt_rand()据说这是提供更好的结果。 但有多好这些结果? 是否有任何改善它们的方法来着?

我的想法:

function rand_best($min, $max) {
    $generated = array();
    for ($i = 0; $i < 100; $i++) {
        $generated[] = mt_rand($min, $max);
    }
    shuffle($generated);
    $position = mt_rand(0, 99);
    return $generated[$position];
}

这应该给你“完美”的随机数,不应该吗?

Answer 1:

伪随机数生成器 (PRNG)是非常复杂的野兽。

有没有真正的“完美”的随机数生成器 - 事实上,可以从数学函数来完成最好的是伪随机 - 他们似乎足够的随机对大多数的意图和目的。

事实上,执行从由PRNG返回并没有真正提高其随机性多项任何附加动作,而事实上,这个数字可能变得不那么随意。

所以,我最好的建议是,不要乱用左右从PRNG的返回值。 使用PRNG是达到预定可使用足够好,如果不是,那么找到,如果有必要,可以产生更好的效果,一个PRNG。

坦率地说,它看来mt_rand函数使用梅森捻线机 ,这是一个相当不错的PRNG,因为它是,那么它可能会成为最随意的使用不够好。

然而, 梅森难题并没有设计任何安全上下文中使用 。 见这个答案 ,因为当你需要的随机性,以确保安全使用的解决方案。

编辑

有没有在评论为什么一个随机数进行操作可以使随机的一个问题。 例如,某些的PRNG可以在比特的不同部分返回更一致的,更少的随机数 - 高端可以比低端更随机。

因此,在操作,其中高端被丢弃,并且被返回的低端,该值可以变得比从PRNG返回原始值以下随机的。

我找不到此刻一个很好的解释,但根据我从为Java文档Random.nextInt(int)方法,其目的是建立在指定范围相当随机的值。 该方法考虑到了的值的部分的随机性的差,所以它可以返回一个更好的随机数相比较,以更幼稚的实现,例如rand() % range



Answer 2:

快速回答:

在新PHP7存在的一个终于支持加密安全伪随机整数。

int random_int ( int $min , int $max )

还有一个用于PHP5x填充工具 。

更长的答案


没有完美的随机数生成器和计算机使用伪随机数生成器来创建一个看起来随机序列。 该序列看起来是随机的(并且通过一些随机性测试 ),但因为有一些算法来生成它,你可以重复算法绝对相同的状态,并得到同样的结果。

同样的建议与密码学 “不发明自己的暗号”,可以翻译为随机数生成器,并意味着你不能只是得到了很多的随机数生成器结合在一起,并得到期望得到更好的发电机。


一个随机数生成的子集是加密安全随机数生成器 :

一个普通的PRNG的要求也由加密安全PRNG满意,但反之则不然。 CSPRNG需求分为两类:第一,它们通过统计随机性测试; 其次,即使在其初始或运行状态的一部分可用来攻击他们托起受到严重的攻击,

所以这是非常接近你的“ 完美 ”的定义。 无条件下一次(除了学习如何做密码的),你应该试图实现算法中的一个,并在系统中使用它。


但幸运的是PHP7有它执行,

int random_int ( int $min , int $max )

生成适合于使用其中无偏的结果是至关重要的(即混洗扑克机)加密的随机整数。

是随机的来源如下:

  • 在Windows CryptGenRandom()是专门用来
  • arc4random_buf()用于如果它是可用的(通常BSD特异性)
  • 的/ dev / ARANDOM用于指可用
  • 所述getrandom(2)系统调用(在较新的Linux内核)
  • 的/ dev / urandom的情况下,使用上述均不可用

这使得以前所有的答案过时的(和一些过时的)。



Answer 3:

我不知道你做了什么“改善”的随机性。 从我能理解你生成100张随机数,然后随机挑选其中之一。

从我可以从我的概率当然记得,这可能不会增加随机性,仿佛有发电机功能的潜在偏见(mt_rand()),那么它仍然会以某种方式在输出反映。



Answer 4:

以何种方式是mt_rand()“坏”?

例如:如果它有利于一定数量。 比方说mt_rand(1,10)有利于低的数字范围,例如“1”和“2”上的每个平均超过10%的发生。 然后你的“改善”将仍然有同样的问题。

选择一个随机数出一个错误的序列仍然是错误的。



Answer 5:

<?php
  function random_number(){
      return 4; // return generated number
                // guaranteed to be random
  }
  ?>

玩笑归玩笑,你要成什么,什么是“随机”一个哲学问题或者是“最好的”。 理想情况下,你会希望你的随机数字在你的程序的过程中都有几个模式。 一般系统时间被用作种子,但我也用以前的随机数作为种子,以前的随机numberth前作为种子。 问题是,有一个足够强大的计算机和硬件运行的充分了解,以及发电机的功能,你就可以预测整个集合生成的数字。 因此,如果你有一个足够强大的计算机(也有人把神这一类)是知道宇宙的所有可能的变量和函数,你可据此预测,发生或将要发生的每一个事件。 多数随机数发生器是对自己很好,但如果你知道谁可以看到的图案,他们越有可能喜欢在美丽心灵的家伙,你应该让他们住进了一家诊所。

大众的需求 :d



Answer 6:

我写了一个cronjob从周期性random.org得到1000个号码(比如说,一个小时一次),并加入他们进入一个PHP数组。 每当我想在我的剧本的随机数,我用mt_rand(0,1000)来调用一个号码。 架空一些额外的微妙,但我得到基于天然大气噪声真正的随机数。



Answer 7:

这一切都取决于你需要什么随机数:)对我来说ShuffleBag是最好的:)



Answer 8:

编辑:我的评论不再有效。 请看下面的答案: https://stackoverflow.com/a/31443898/109561


我猜你担心mt_rand的分布()。 我测试了它,它是很有层次和范围都包含在内。

我说我的测试,为mt_rand()的PHP手册文档的评论,但它是由一个愚蠢的主持人删除,由于这些太长篇大论进入这里的政治。



Answer 9:

如果你不喜欢PHP的内置rand()你可能不应该用自己的内置shuffle()要么,因为它似乎是在其内置rand()

我中途肯定的“行业标准”洗牌现在是费雪耶茨洗牌。



Answer 10:

有一个“完美”的随机数,没有这样的事。 不管你有什么主观的“完美”的定义。 您只能达到伪随机的。

我无非是想给你指出正确的方向。 你问了一个近乎完美的随机数的问题,即使是完美的报价。 是的,你可以提高随机性。 你甚至可以实现启发式或“天然”的算法,这样的想法,如“大气噪声” - 但仍然,你不是完美的,不以任何方式。



Answer 11:

使用/ dev / ramdom(linux设备真随机数生成器)种子mt_rand

<?
$rnd_dev=mcrypt_create_iv(4, MCRYPT_DEV_RANDOM); //need "apt-get install php5-mcrypt"
$seed=ord(substr($rnd_dev, 0, 1))<<24 |
      ord(substr($rnd_dev, 1, 1))<<16 |
      ord(substr($rnd_dev, 2, 1))<<8 |
      ord(substr($rnd_dev, 3, 1));
mt_srand($seed);
echo mt_rand();
?>


Answer 12:

我做了一个PHP类用于生成随机数和字符串PHPRandomValue

它使用“mcrypt_create_iv(4,MCRYPT_DEV_URANDOM)”来产生随机数和值。 我做了一个加密项目时,因为我需要一个安全的随机值发生器。 这里有一个例子使用

$randomValue = new RandomValue;

$randomValue->randomNumber(): = -3880998

$randomValue->randomNumberBetween(1,10): = 2

$randomValue->randomTextString(): = CfCkKDHRgUULdGWcSqP4

$randomValue->randomTextString(10):  = LorPIxaeEY

$randomValue->randomKey(): = C7al8tX9.gqYLf2ImVt/!$NOY79T5sNCT/6Q.$!.6Gf/Q5zpa3

$randomValue->randomKey(10):  = RDV.dc6Ai/


Answer 13:

这是不可能产生真正的随机数,你可以期望的最好的是伪随机而这正是兰特()提供,你的功能是没有接近随机然后兰特()。 看看这个http://en.wikipedia.org/wiki/Random_number_generator



Answer 14:

TRU随机数

<?php
for ($i = -1; $i <= 4; $i++) {
    $bytes = openssl_random_pseudo_bytes($i, $cstrong);
    $hex   = bin2hex($bytes);

    echo "Lengths: Bytes: $i and Hex: " . strlen($hex) . PHP_EOL;
    var_dump($hex);
    var_dump($cstrong);
    echo PHP_EOL;
}
?>

而且密码安全;)



Answer 15:

虽然答案年前接受了,我会再重新打开它。

由于这一切的随机性取决于系统的时间,让我们与系统时间太乱了! 时间的操作需要在计算机上的量其实是没有变化(特别是如果其他的东西是发生在该服务器上),所以如果我们利用这一点与microtime中......(找不到任何便携式nanotime命令)

$a='';
for (int $i=0; $i<9001; $i++)
{
    usleep(mt_rand(1000,10000));//Also eliminates timing attacks... possibly?
    $a=hash('SHA512',$a.uniqid(mt_rand().microtime(),true));
}
echo $a;

名义上这有熵207023位,因为您要添加其他23位的每一次迭代,但有很多相互依赖的,所以它可能是数量级的几个订单较少。 还是蛮不错的。

你知道吗,需要大量的时间真正随机的PHP上的任何操作的? 像... HTTP的请求一些网站(比RANDOM.org等)和测量所花费的时间?



Answer 16:

使用random.org,您可以使用此:

function getToken($length, $min, $max){
    $r = explode('
',file_get_contents('http://www.random.org/integers/num='.$length.'&min='.$min.'&max='.$max.'&col=1&base=10&format=plain'));

    $string = '';
    foreach ( $r as $char ) $string.=$char;
    return $string;
}

这应该给真正的随机数



文章来源: Generate cryptographically secure random numbers in php