如何使用bcrypt在PHP中哈希密码? [英] How do you use bcrypt for hashing passwords in PHP?

查看:438
本文介绍了如何使用bcrypt在PHP中哈希密码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

现在,我听到使用bcrypt在PHP中存储密码,bcrypt规则的建议。

Every now and then I hear the advice "Use bcrypt for storing passwords in PHP, bcrypt rules".

但是什么是 bcrypt ? PHP不提供任何这样的功能,维基百科关于文件加密实用程序和Web搜索只是揭示了一些河豚在不同的语言。现在Blowfish也可以通过 mcrypt 在PHP,但是如何帮助存储密码? Blowfish是一个通用密码,它工作有两种方式。如果它可以被加密,它可以被解密。密码需要单向哈希函数。

But what is bcrypt? PHP doesn't offer any such functions, Wikipedia babbles about a file-encryption utility and Web searches just reveal a few implementations of Blowfish in different languages. Now Blowfish is also available in PHP via mcrypt, but how does that help with storing passwords? Blowfish is a general purpose cipher, it works two ways. If it could be encrypted, it can be decrypted. Passwords need a one-way hashing function.

解释方法是什么?

推荐答案

bcrypt 是一种散列算法,可以通过硬件(通过可配置的轮数)进行扩展。它的缓慢和多轮,确保攻击者必须部署大量的资金和硬件,以能够破解您的密码。添加到每个密码 bcrypt 需要盐),你可以确定攻击几乎是不可行的,没有可靠的资金或硬件。

bcrypt is a hashing algorithm which is scalable with hardware (via a configurable number of rounds). Its slowness and multiple rounds ensures that an attacker must deploy massive funds and hardware to be able to crack your passwords. Add to that per-password salts (bcrypt REQUIRES salts) and you can be sure that an attack is virtually unfeasible without either ludicrous amount of funds or hardware.

bcrypt 使用 Eksblowfish 算法来哈希密码。虽然 Eksblowfish Blowfish 的加密阶段完全相同,但 Eksblowfish 的关键调度阶段确保任何后续状态都取决于salt和密钥(用户密码),并且没有状态可以在没有两者的知识的情况下被预先计算。 由于这个关键区别, bcrypt 是一种单向散列算法。如果不知道盐,rounds 和键(密码)。 [来源]

bcrypt uses the Eksblowfish algorithm to hash passwords. While the encryption phase of Eksblowfish and Blowfish are exactly the same, the key schedule phase of Eksblowfish ensures that any subsequent state depends on both salt and key (user password), and no state can be precomputed without the knowledge of both. Because of this key difference, bcrypt is a one-way hashing algorithm. You cannot retrieve the plain text password without already knowing the salt, rounds and key (password). [Source]

密码散列函数现在已经直接构建到PHP> = 5.5 。您现在可以使用 password_hash() 创建 bcrypt 任何密码的散列:

Password hashing functions have now been built directly into PHP >= 5.5. You may now use password_hash() to create a bcrypt hash of any password:

<?php
// Usage 1:
echo password_hash('rasmuslerdorf', PASSWORD_DEFAULT)."\n";
// $2y$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// For example:
// $2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

// Usage 2:
$options = [
  'cost' => 11
];
echo password_hash('rasmuslerdorf', PASSWORD_BCRYPT, $options)."\n";
// $2y$11$6DP.V0nO7YI3iSki4qog6OQI5eiO6Jnjsqg7vdnb.JgGIsxniOn4C

验证用户提供的密码针对现有的哈希,您可以使用 password_verify()

To verify a user provided password against an existing hash, you may use the password_verify() as such:

<?php
// See the password_hash() example to see where this came from.
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';

if (password_verify('rasmuslerdorf', $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}



使用PHP> = 5.3.7, 5.5-DEV(也是RedHat PHP> = 5.3.3)



兼容性在 GitHub 上创建基于上述函数的源代码的库,这些函数最初是用C编写的,它提供了功能。一旦安装了兼容性库,使用方法与上面相同(如果你仍然在5.3.x分支上,则减去简写数组符号)。

Using PHP >= 5.3.7, < 5.5-DEV (also RedHat PHP >= 5.3.3)

There is a compatibility library on GitHub created based on the source code of the above functions originally written in C, which provides the same functionality. Once the compatibility library is installed, usage is the same as above (minus the shorthand array notation if you are still on the 5.3.x branch).

您可以使用 crypt()输入字符串的bcrypt哈希值。这个类可以自动生成盐和验证现有哈希对输入。 如果您使用的PHP版本高于或等于5.3.7,强烈建议您使用内置函数或compat库。此替代方法仅用于历史目的。

You can use crypt() function to generate bcrypt hashes of input strings. This class can automatically generate salts and verify existing hashes against an input. If you are using a version of PHP higher or equal to 5.3.7, it is highly recommended you use the built-in function or the compat library. This alternative is provided only for historical purposes.

class Bcrypt
{
  private $rounds;

  public function __construct($rounds = 12)
  {
    if (CRYPT_BLOWFISH != 1) {
      throw new Exception("bcrypt not supported in this installation. See http://php.net/crypt");
    }

    $this->rounds = $rounds;
  }

  public function hash($input)
  {
    $hash = crypt($input, $this->getSalt());

    if (strlen($hash) > 13)
      return $hash;

    return false;
  }

  public function verify($input, $existingHash)
  {
    $hash = crypt($input, $existingHash);

    return $hash === $existingHash;
  }

  private function getSalt()
  {
    $salt = sprintf('$2a$%02d$', $this->rounds);

    $bytes = $this->getRandomBytes(16);

    $salt .= $this->encodeBytes($bytes);

    return $salt;
  }

  private $randomState;
  private function getRandomBytes($count)
  {
    $bytes = '';

    if (function_exists('openssl_random_pseudo_bytes') &&
        (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { // OpenSSL is slow on Windows
      $bytes = openssl_random_pseudo_bytes($count);
    }

    if ($bytes === '' && is_readable('/dev/urandom') &&
       ($hRand = @fopen('/dev/urandom', 'rb')) !== FALSE) {
      $bytes = fread($hRand, $count);
      fclose($hRand);
    }

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

      if ($this->randomState === null) {
        $this->randomState = microtime();
        if (function_exists('getmypid')) {
          $this->randomState .= getmypid();
        }
      }

      for ($i = 0; $i < $count; $i += 16) {
        $this->randomState = md5(microtime() . $this->randomState);

        if (PHP_VERSION >= '5') {
          $bytes .= md5($this->randomState, true);
        } else {
          $bytes .= pack('H*', md5($this->randomState));
        }
      }

      $bytes = substr($bytes, 0, $count);
    }

    return $bytes;
  }

  private function encodeBytes($input)
  {
    // The following is code from the PHP Password Hashing Framework
    $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

    $output = '';
    $i = 0;
    do {
      $c1 = ord($input[$i++]);
      $output .= $itoa64[$c1 >> 2];
      $c1 = ($c1 & 0x03) << 4;
      if ($i >= 16) {
        $output .= $itoa64[$c1];
        break;
      }

      $c2 = ord($input[$i++]);
      $c1 |= $c2 >> 4;
      $output .= $itoa64[$c1];
      $c1 = ($c2 & 0x0f) << 2;

      $c2 = ord($input[$i++]);
      $c1 |= $c2 >> 6;
      $output .= $itoa64[$c1];
      $output .= $itoa64[$c2 & 0x3f];
    } while (true);

    return $output;
  }
}

您可以使用此代码:

$bcrypt = new Bcrypt(15);

$hash = $bcrypt->hash('password');
$isGood = $bcrypt->verify('password', $hash);

或者,您也可以使用便携式PHP散列框架

这篇关于如何使用bcrypt在PHP中哈希密码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆