为了账号安全,请及时绑定邮箱和手机立即绑定

在PHP中保护随机数生成

/ 猿问

在PHP中保护随机数生成

茅侃侃 2019-08-08 15:44:21

在PHP中保护随机数生成

使用案例:“我忘了密码”按钮。我们找不到用户的原始密码,因为它以散列形式存储,因此唯一要做的就是生成一个新的随机密码并通过电子邮件发送给他。这需要加密不可预测的随机数,mt_rand不够好,一般我们不能假设托管服务将提供对操作系统的访问以安装加密随机数模块等所以我正在寻找一种方法在PHP本身生成安全的随机数。

到目前为止我提出的解决方案涉及存储初始种子,然后为每次调用,

result = seed
seed = sha512(seed . mt_rand())

这是基于sha512哈希函数的安全性(mt_rand调用只是为了获得数据库副本的对手的生活有点困难)。

我错过了什么,还是有更好的解决方案?


查看完整描述

3 回答

?
不负相思意

您还可以考虑使用OpenSSL openssl_random_pseudo_bytes,它自PHP 5.3起可用。

 string openssl_random_pseudo_bytes ( int $length [, bool &$crypto_strong ] )

生成一串伪随机字节,其长度参数确定的字节数。它还指示是否使用加密强算法来生成伪随机字节,并通过可选的crypto_strong参数执行此操作。这种情况很少见,但有些系统可能会损坏或过时。

http://www.php.net/manual/en/function.openssl-random-pseudo-bytes.php

从PHP 7开始,还有random_bytes功能可用

string random_bytes ( int $length )

http://php.net/manual/en/function.random-bytes.php


查看完整回答
反对 回复 2019-08-08
?
慕森王

我强烈建议在unix系统上使用/ dev / urandom或在windows平台上使用crypto-api作为密码的熵源。

我不能强调实现哈希的重要性不是神奇的增加熵的设备。以这种方式滥用它们并不比使用种子和rand()数据在散列之前更安全,我确信你认识到这不是一个好主意。种子取消了(确定性的mt_rand()),所以即使包括它也没有任何意义。

人们认为他们聪明聪明,他们的劳动成果是脆弱的系统和设备,使他们的系统安全和其他系统的安全(通过糟糕的建议)处于不必要的危险之中。

两个错误并不是正确的。一个系统只有它最薄弱的部分一样强大。这不是接受使其更加不安全的许可或借口。


下面是一些PHP代码来获取一个安全的随机128位字符串,来自php.net的评论Mark Seecof

“如果你需要一些伪随机位用于安全或加密目的(egg,随机IV用于分组密码,随机盐用于密码散列)mt_rand()是一个很差的来源。在大多数Unix / Linux和/或MS-Windows平台上,你可以获得来自OS或系统库的更好等级的伪随机位,如下所示:

<?php// get 128 pseudorandom bits in a string of 16 bytes$pr_bits = '';// Unix/Linux platform?$fp = @fopen('/dev/urandom','rb');if ($fp !== FALSE) {
    $pr_bits .= @fread($fp,16);
    @fclose($fp);}// MS-Windows platform?if (@class_exists('COM')) {
    // http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx
    try {
        $CAPI_Util = new COM('CAPICOM.Utilities.1');
        $pr_bits .= $CAPI_Util->GetRandom(16,0);

        // if we ask for binary data PHP munges it, so we
        // request base64 return value.  We squeeze out the
        // redundancy and useless ==CRLF by hashing...
        if ($pr_bits) { $pr_bits = md5($pr_bits,TRUE); }
    } catch (Exception $ex) {
        // echo 'Exception: ' . $ex->getMessage();
    }}if (strlen($pr_bits) < 16) {
    // do something to warn system owner that
    // pseudorandom generator is missing}?>

注意:保留读取/ dev / urandom的尝试和代码中访问CAPICOM的尝试通常是安全的,尽管每个都会在另一个平台上静默失败。把它们留在那里,这样你的代码就会更便携。“


查看完整回答
反对 回复 2019-08-08
?
摇曳的蔷薇

PHP附带了一组新的CSPRNG函数(random_bytes()random_int())。将后一个函数转换为字符串生成器函数是微不足道的:

<?php/**
 * Generate a random string, using a cryptographically secure 
 * pseudorandom number generator (random_int)
 * 
 * For PHP 7, random_int is a PHP core function
 * For PHP 5.x, depends on https://github.com/paragonie/random_compat
 * 
 * @param int $length      How many characters do we want?
 * @param string $keyspace A string of all possible characters
 *                         to select from
 * @return string
 */function random_str(
    $length,
    $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
    $str = '';
    $max = mb_strlen($keyspace, '8bit') - 1;
    if ($max < 1) {
        throw new Exception('$keyspace must be at least two characters long');
    }
    for ($i = 0; $i < $length; ++$i) {
        $str .= $keyspace[random_int(0, $max)];
    }
    return $str;}

如果您需要在PHP 5项目中使用它,请随意获取random_compat的副本,random_compat是这些函数的polyfill


查看完整回答
反对 回复 2019-08-08

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信