Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这在PHP中是一个很好的哈希密码函数吗?若否,原因为何?_Php_Security_Passwords_Cryptography_Password Hash - Fatal编程技术网

这在PHP中是一个很好的哈希密码函数吗?若否,原因为何?

这在PHP中是一个很好的哈希密码函数吗?若否,原因为何?,php,security,passwords,cryptography,password-hash,Php,Security,Passwords,Cryptography,Password Hash,我想知道这个函数是否足够好(它的一部分来自一个2年前的phpBB版本) 如果没有,原因是什么? 您将如何改变它(为现有用户实现无缝过渡) hash_pwd()的结果将保存在数据库中 函数hash_pwd($password) { $itoa64='/0123456789ABCDEFGHIjklmnopqrstuvxyzABEFGHIjklmnopqrstuvxyz'; $random_state=$this->unique_id(); $random=''; $count=6; 如果($fh=

我想知道这个函数是否足够好(它的一部分来自一个2年前的phpBB版本)

如果没有,原因是什么?
您将如何改变它(为现有用户实现无缝过渡)

hash_pwd()的结果将保存在数据库中

函数hash_pwd($password)
{
$itoa64='/0123456789ABCDEFGHIjklmnopqrstuvxyzABEFGHIjklmnopqrstuvxyz';
$random_state=$this->unique_id();
$random='';
$count=6;
如果($fh=@fopen('/dev/uradom','rb'))
{
$random=fread($fh,$count);
fclose($fh);
}
if(strlen($random)<$count)
{
$random='';
对于($i=0;$i<$count;$i+=16)
{
$random\u state=md5($this->unique\u id().$random\u state);
$random.=pack('H*',md5($random_state));
}
$random=substr($random,0,$count);
}
$hash=$this->\u hash\u crypt\u private($password,$this->\u hash\u gensalt\u private($random,$itoa64),$itoa64);
if(strlen($hash)==34)
{
返回$hash;
}
返回false;
}
函数唯一\u id()
{
$val=微时间();
$val=md5($val);
返回substr($val,4,16);
}
函数_hash_crypt_private($password、$setting和$itoa64)
{
$output='*';
//检查哈希是否正确
如果(substr($setting,0,3)!=“$H$”)
{
返回$output;
}
$count_log2=strpos($itoa64,$setting[3]);
如果($count_log2<7||$count_log2>30)
{
返回$output;
}
$count=1=5)
{
$hash=md5($salt.$password,true);
做
{
$hash=md5($hash.$password,true);
}
而(-$count);
}
其他的
{
$hash=pack('H*',md5($salt.$password));
做
{
$hash=pack('H*',md5($hash.$password));
}
而(-$count);
}
$output=substr($setting,0,12);
$output.=$this->\u hash\u encode64($hash,16,$itoa64);
返回$output;
}
函数\u hash\u gensalt\u private($input,&$itoa64,$iteration\u count\u log2=6)
{
如果($iteration_count_log2<4||$iteration_count_log2>31)
{
$iteration\u count\u log2=8;
}
$output='$H$';
$output.=$itoa64[min($iteration\u count\u log2+((PHP\u VERSION>=5)?5:3),30)];
$output.=$this->\u hash\u encode64($input,6,$itoa64);
返回$output;
}
函数_hash_encode64($input、$count和$itoa64)
{
$output='';
$i=0;
做
{
$value=ord($input[$i++]);
$output.=$itoa64[$value&0x3f];
如果($i<$count)
{
$value |=ord($input[$i])>6)和0x3f];
如果($i++>=$count)
{
打破
}
如果($i<$count)
{
$value |=ord($input[$i])>12)和0x3f];
如果($i++>=$count)
{
打破
}
$output.=$itoa64[($value>>18)&0x3f];
}
而($i<$count);
返回$output;
}

快速回答:

使用或从ircmaxell库-它是一个bcrypt库

长答案:

对于目前的技术来说,这太复杂和过时了。应该避免使用Md5,仅仅用盐腌制是不够的。使用bcrypt,省得你自己头疼

您可能会问自己为什么要使用这个特定的库?php 5.5中也会提供相同的函数,因此您不必更改任何编码。祝您好运,并保持它的简单和高效。同时,速度慢对于登录和密码之类的东西也有好处

更新1

@Gumbo->No MD5没有被破坏,但是像MD5这样的散列现在和过去的主要用途是用于文件检查(正如您所知,检查文件的内容是否可信,而不是密码存储)由于散列的破译速度非常快,因为等待30-45秒后,您不会使用Bcrypt检查文件内容……因此这意味着散列的读取速度特别快。即使是SHA512与Bcrypt相比,也完全不如Bcrypt。这就是为什么必须推动像Blowfish/B这样的强大密码算法的原因作为用户和程序员,我们必须扩展知识,简单的密码存储或低级散列算法不是答案,而且永远不应该用于此类敏感信息

现在转到OP,要转换到新系统,您首先要向所有用户发送通知,说明“为了您的安全,密码加密系统已更新……”,然后您会要求他们进行一次性密码更新,一旦您进行了密码更新,您将使用名为password\u verify的函数,如果您希望最大限度地控制成本比率,则如果出于某种原因选择更改与密码相关的成本,您将使用password\u needs\u rehash

这不需要大量的代码块来完成,因为密码保护带来的好处超过了“重新编码”新密码系统的负面影响

希望这能回答大多数问题,但尽管如此,IRCmaxell的答案还是远远优于其他算法!祝您好运,感谢IRCmaxell

更新2


另外,像这样存储的密码真的可以破解吗?如何破解?(我现在很好奇)

我的网络安全教授告诉我,任何东西和任何东西都是坏的……我嘲笑他。现在我从他的眼睛里看到了东西……是的……那绝对是真的

Bcrypt目前是存储密码的最佳方法!但是,如果你研究一下似乎很有前途但PHP不支持的Scrypt。尽管如此,任何东西都会被破坏,直到某个“极客”出现只是时间问题在地下室里,Bcrypt会破裂。但现在我们是安全的。就像IPv4永远不会耗尽一样……哦,等等?…)<
function hash_pwd($password)
{
    $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';

    $random_state = $this->unique_id();
    $random = '';
    $count = 6;

    if (($fh = @fopen('/dev/urandom', 'rb')))
    {
        $random = fread($fh, $count);
        fclose($fh);
    }

    if (strlen($random) < $count)
    {
        $random = '';

        for ($i = 0; $i < $count; $i += 16)
        {
            $random_state = md5($this->unique_id() . $random_state);
            $random .= pack('H*', md5($random_state));
        }
        $random = substr($random, 0, $count);
    }

    $hash = $this->_hash_crypt_private($password, $this->_hash_gensalt_private($random, $itoa64), $itoa64);

    if (strlen($hash) == 34)
    {
        return $hash;
    }

    return false;
}


function unique_id()
{
    $val = microtime();
    $val = md5($val);

    return substr($val, 4, 16);
}

function _hash_crypt_private($password, $setting, &$itoa64)
{
    $output = '*';

    // Check for correct hash
    if (substr($setting, 0, 3) != '$H$')
    {
        return $output;
    }

    $count_log2 = strpos($itoa64, $setting[3]);

    if ($count_log2 < 7 || $count_log2 > 30)
    {
        return $output;
    }

    $count = 1 << $count_log2;
    $salt = substr($setting, 4, 8);

    if (strlen($salt) != 8)
    {
        return $output;
    }

    /**
    * We're kind of forced to use MD5 here since it's the only
    * cryptographic primitive available in all versions of PHP
    * currently in use.  To implement our own low-level crypto
    * in PHP would result in much worse performance and
    * consequently in lower iteration counts and hashes that are
    * quicker to crack (by non-PHP code).
    */
    if (PHP_VERSION >= 5)
    {
        $hash = md5($salt . $password, true);
        do
        {
            $hash = md5($hash . $password, true);
        }
        while (--$count);
    }
    else
    {
        $hash = pack('H*', md5($salt . $password));
        do
        {
            $hash = pack('H*', md5($hash . $password));
        }
        while (--$count);
    }

    $output = substr($setting, 0, 12);
    $output .= $this->_hash_encode64($hash, 16, $itoa64);

    return $output;
}

function _hash_gensalt_private($input, &$itoa64, $iteration_count_log2 = 6)
{
    if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31)
    {
        $iteration_count_log2 = 8;
    }

    $output = '$H$';
    $output .= $itoa64[min($iteration_count_log2 + ((PHP_VERSION >= 5) ? 5 : 3), 30)];
    $output .= $this->_hash_encode64($input, 6, $itoa64);

    return $output;
}

function _hash_encode64($input, $count, &$itoa64)
{
    $output = '';
    $i = 0;

    do
    {
        $value = ord($input[$i++]);
        $output .= $itoa64[$value & 0x3f];

        if ($i < $count)
        {
            $value |= ord($input[$i]) << 8;
        }

        $output .= $itoa64[($value >> 6) & 0x3f];

        if ($i++ >= $count)
        {
            break;
        }

        if ($i < $count)
        {
            $value |= ord($input[$i]) << 16;
        }

        $output .= $itoa64[($value >> 12) & 0x3f];

        if ($i++ >= $count)
        {
            break;
        }

        $output .= $itoa64[($value >> 18) & 0x3f];
    }
    while ($i < $count);

    return $output;
}
a-zA-Z0-9~`!@#$%^&*()_+-={}|[]\:";'<>,.?/
private function generateSalt() {
  $salt = '';
  $i = rand(20, 40); //min,max length
  for($length = 0; $length < $i; $length++) {
    $salt .= chr(rand(33, 126));
  }        
  return $salt;
}
private function generatePass() {
  $vocabulary = 'abcdefghijklmnopqrstuvwxyz0123456789';
  $password = '';
  $i = rand(7,10);
  for($length = 0; $length < $i; $length++) {
      $password .= substr($vocabulary,rand(0, 35),1);
  }        
  return $password.'-'; // avoid copy`n`paste :)
}
$newSalt = $this->generateSalt();
$newPass = $this->generatePass();
$newHash = hash('sha512', $newPass.':'.$newSalt); 
// now store hash and salt into database