如何使用bcrypt在PHP中对密码进行哈希处理?


1255

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

但是什么bcrypt呢?PHP不提供任何此类功能,维基百科对文件加密实用程序不屑一顾,而Web搜索仅显示了几种以不同语言实现的Blowfish实现。现在Blowfish也可以通过PHP在PHP中使用mcrypt,但这对存储密码有何帮助?河豚是一种通用密码,它有两种工作方式。如果可以加密,则可以解密。密码需要单向散列功能。

有什么解释?


13
之前已经解决了这个问题,他们对使用标准库的建议非常好。安全是一件复杂的事情,使用由知道自己在做什么的人设计的程序包只会帮助自己。
eykanal 2011年

59
@eykanal-该页面甚至没有提到bcrypt,更不用说它了
Vilx- 2011年

8
@eykanal-我不要求对其工作方式进行解释。我只想知道那是什么。因为我可以在网络上使用关键字“ bcrypt”进行挖掘,所以无论如何都不能用于哈希密码。无论如何,不​​是直接的,也不是在PHP中。好的,到目前为止,我知道这是真正的“ phpass”软件包,它使用河豚通过从您的密码派生而来的密钥来加密您的密码(本质上是用自身加密密码)。但是,将其称为“ bcrypt”会造成严重误导,这就是我想在此问题中阐明的内容。
Vilx- 2011年

3
@Vilx:我已经添加了更多的信息,为什么bcrypt是单向散列算法与加密方案在我的答案。整个误解bcrypt只是河豚,实际上它的密钥调度完全不同,这确保了在不知道密码初始状态(盐,回合,密钥)的情况下,无法从密文中恢复纯文本。
Andrew Moore

1
另请参见Openwall的可移植PHP密码哈希框架(PHPass)。它可以抵抗许多常见的用户密码攻击。
2014年

Answers:


1065

bcrypt是一种哈希算法,可通过硬件(通过可配置的回合数)进行扩展。它的缓慢性和多次回合确保了攻击者必须部署大量资金和硬件才能破解您的密码。加上每个口令的bcrypt需要盐),您可以确定,如果没有可笑的资金或硬件,攻击实际上是不可行的。

bcrypt使用Eksblowfish算法对密码进行哈希处理。虽然EksblowfishBlowfish的加密阶段完全相同,但是Eksblowfish的密钥调度阶段可确保任何后续状态都取决于salt和密钥(用户密码),并且在不了解这两个状态的情况下无法对它们进行预先计算。由于存在这一关键差异,因此bcrypt是一种单向哈希算法。在不知道盐,四舍五入和密钥(密码)的情况下,您无法检索纯文本密码。[ 来源 ]

如何使用bcrypt:

使用PHP> = 5.5-DEV

密码哈希函数现已直接内置到PHP> = 5.5中。您现在可以password_hash()用来创建bcrypt任何密码的哈希值:

<?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()

<?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分支上,请减去简写数组符号)。

使用PHP <5.3.7 (不建议使用

您可以使用crypt()函数来生成输入字符串的bcrypt散列。此类可以自动生成盐,并根据输入来验证现有哈希。如果您使用的PHP版本高于或等于5.3.7,则强烈建议您使用内置函数或compat库。仅出于历史目的提供此替代方法。

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);

另外,您也可以使用Portable PHP Hashing Framework


7
@The Wicked Flea:对不起,您很失望,但mt_rand()也使用当前时间和当前进程ID作为种子。请参阅GENERATE_SEED()/ext/standard/php_rand.h
Andrew Moore

53
@Mike:继续吧,正是因为这个原因!
安德鲁·摩尔

14
对于认为需要在getSalt函数中修改$ salt字符串开头的任何人,这都是没有必要的。$ 2a $ __是CRYPT_BLOWFISH盐的一部分。来自文档:“河豚用盐散列如下:“ $ 2a $”,两位数的成本参数“ $”和字母中的22位。
jwinn 2011年

18
@MichaelLang:好事crypt()要经过同行评审和验证。上面的代码调用PHP的crypt(),后者调用POSIX crypt()函数。上面的所有代码做的更多的是在调用之前生成了一个随机盐(不必具有加密安全性,盐不被视为秘密)crypt()也许您应该在打电话给狼之前先做一些研究。
安德鲁·摩尔

31
请注意,这个答案虽然不错,但开始显示它的年龄。此代码(像任何依赖于PHP的实现一样crypt())受5.3.7之前的安全漏洞的影响,并且在5.3.7之后的效率非常低下-有关此问题的详细信息,请参见此处。另请注意,新的密码哈希APIbackwards compat lib)现在是在您的应用程序中实现bcrypt密码哈希的首选方法。
DaveRandom

295

那么,您要使用bcrypt吗?太棒了!但是,与其他密码学领域一样,您不应该自己进行加密。如果您需要担心诸如管理密钥,存储盐或生成随机数之类的事情,那您就错了。

原因很简单:搞砸bcrypt非常容易。实际上,如果您查看此页面上几乎所有的代码,都会注意到它至少违反了这些常见问题之一。

面对现实,密码学很难。

留给专家。将其留给维护这些库的工作人员使用。如果您需要做出决定,那就错了。

相反,只需使用一个库。根据您的要求有几种。

图书馆

这是一些更常见的API的细分。

PHP 5.5 API-(适用于5.3.7+)

从PHP 5.5开始,引入了用于哈希密码的新API。(我)还为5.3.7+维护了一个垫片兼容性库。这具有被同行评审和易于使用的实现的好处。

function register($username, $password) {
    $hash = password_hash($password, PASSWORD_BCRYPT);
    save($username, $hash);
}

function login($username, $password) {
    $hash = loadHashByUsername($username);
    if (password_verify($password, $hash)) {
        //login
    } else {
        // failure
    }
}

确实,它的目标是非常简单。

资源:

Zend \ Crypt \ Password \ Bcrypt(5.3.2+)

这是另一个类似于PHP 5.5的API,并且具有相似的用途。

function register($username, $password) {
    $bcrypt = new Zend\Crypt\Password\Bcrypt();
    $hash = $bcrypt->create($password);
    save($user, $hash);
}

function login($username, $password) {
    $hash = loadHashByUsername($username);
    $bcrypt = new Zend\Crypt\Password\Bcrypt();
    if ($bcrypt->verify($password, $hash)) {
        //login
    } else {
        // failure
    }
}

资源:

密码库

这是密码哈希的稍微不同的方法。PasswordLib不仅支持bcrypt,还支持大量的哈希算法。它主要用于需要支持与您控制范围之外的旧系统和异构系统的兼容性的情况。它支持大量的哈希算法。并支持5.3.2+

function register($username, $password) {
    $lib = new PasswordLib\PasswordLib();
    $hash = $lib->createPasswordHash($password, '$2y$', array('cost' => 12));
    save($user, $hash);
}

function login($username, $password) {
    $hash = loadHashByUsername($username);
    $lib = new PasswordLib\PasswordLib();
    if ($lib->verifyPasswordHash($password, $hash)) {
        //login
    } else {
        // failure
    }
}

参考文献:

PHPASS

这是一个确实支持bcrypt的层,但是它还支持相当强大的算法,如果您无法访问PHP> = 5.3.2 ...,该算法将非常有用。它实际上支持PHP 3.0+(尽管不支持bcrypt)。

function register($username, $password) {
    $phpass = new PasswordHash(12, false);
    $hash = $phpass->HashPassword($password);
    save($user, $hash);
}

function login($username, $password) {
    $hash = loadHashByUsername($username);
    $phpass = new PasswordHash(12, false);
    if ($phpass->CheckPassword($password, $hash)) {
        //login
    } else {
        // failure
    }
}

资源资源

注意:不要使用不在openwall上托管的PHPASS替代方案,它们是不同的项目!!!

关于BCrypt

如果您注意到这些库中的每一个都返回一个字符串。这是因为BCrypt在内部如何工作。关于这一点有很多答案。这是我写的选择,我不会在这里复制/粘贴,但链接到:

包起来

有很多不同的选择。选择哪种取决于您。但是,我强烈建议您使用上述库之一为您处理此问题。

同样,如果您crypt()直接使用,则可能是做错了什么。如果您的代码直接使用hash()(或md5()sha1()),则几乎肯定是在做错什么。

只是使用图书馆...


7
盐必须是随机生成的,但是它不必来自安全的随机来源。盐不是秘密。能够猜测下一个盐不会真正影响安全性;只要它们来自足够大的数据池以为每个编码的密码生成不同的盐,就可以了。请记住,如果您的哈希表落入坏人的手中,则盐会阻止使用彩虹表。他们不是秘密。
Andrew Moore

7
@AndrewMoore绝对正确!但是,盐必须具有足够的熵才能在统计上是唯一的。不仅在您的应用程序中,而且在所有应用程序中。因此mt_rand()具有足够高的周期,但种子值仅为32位。因此,mt_rand()有效地将您限制为仅32位熵。多亏了生日问题,这意味着您(全球)仅产生7k盐就有50%的碰撞机会。由于bcrypt可以接受128位盐,因此最好使用可以提供全部128位;-)的信号源。(在128位时,发生2e19哈希时发生冲突的机会为50%)...
ircmaxell 2013年

1
@ircmaxell:修饰“足够大的数据池”。但是,您的源不必是非常高的熵源,只需足够用于128位。但是,如果您用尽了所有可用的资源(没有OpenSSL等),而唯一的后备是mt_rand(),则它仍然比替代方法(即rand())更好。
Andrew Moore

4
@AndrewMoore:绝对。不争辩。只是mt_randuniqid(以及因此lcg_valuerand)并不是首选...
ircmaxell 2013年

1
ircmaxell,非常感谢您使用5.3.xx的password_compat库,我们以前并不需要它,但是现在我们在5.3.xx php服务器上需要它,并且感谢您的明确建议,不要尝试执行此逻辑自己。
Lizardx

47

在“ Rainbow Tables足够了”中,您将获得很多信息:有关安全密码方案可移植PHP密码哈希框架的知识

目标是用较慢的速度对密码进行哈希处理,因此,获得密码数据库的某人将试图强行使用它会死掉(延迟10毫秒来检查密码对您而言无济于事,对于试图对其进行强行使用的人来说,这是很多事情)。Bcrypt很慢,可以与参数一起使用以选择它的速度。


7
强制执行您想要的任何操作,用户将设法搞砸并在多个方面使用相同的密码。因此,您必须尽可能地保护它或实施一些不必存储任何密码(SSO,openID等)的操作。
2011年

41
否。密码哈希用于防止一种攻击:某人偷了您的数据库并想获取明文登录名和密码。
2011年

4
@Josh K.我鼓励您尝试通过phpass调整后破解一些简单的密码,以便在Web服务器上计算该密码需要1ms到10ms的时间。
2011年

3
同意 但是,将使用qwerty作为密码的用户也是那种会在他(和攻击者)可以轻松阅读的地方标记任何复杂密码的用户。使用bcrypt可以完成的工作是,当您的数据库违反您的意愿公开发行时,要比拥有一遍使用sha512的用户更难获得拥有^ | $$&ZL6-£之类的密码的用户。
2011年

4
值得一提的是,@ coreyward这样做比根本不进行阻止更具危害性;很容易被视为“拒绝服务”向量。只需开始在任何已知帐户上发送错误的登录名,您就可以非常非常轻松地破坏许多用户。阻止(延迟)攻击者比完全拒绝访问更好,尤其是如果它是付费客户时。
damianb

36

您可以使用PHP crypt()函数使用bcrypt创建单向哈希,并传入适当的河豚盐。整个方程式中最重要的是A)算法没有受到破坏,B)您正确地给每个密码加了盐。不要在应用程序范围内使用盐;这将打开您的整个应用程序,以从一组Rainbow表进行攻击。

PHP-地穴功能


4
这是正确的方法-使用PHP的crypt()函数,该函数支持几种不同的密码哈希函数。确保您没有使用CRYPT_STD_DESCRYPT_EXT_DES-其他任何受支持的类型都很好(并且包括bcrypt,名称为CRYPT_BLOWFISH)。
caf

4
通过“回合”选项,SHA确实也具有成本参数。当使用它时,我也没有理由支持bcrypt。
Pieter Ennes

3
实际上,单个SHA-1(或MD5)密码仍然很容易被暴力破解,无论是否加盐(盐有助于防止彩虹表,而非暴力破解)。使用bcrypt。
圣保罗Ebermann

我感到不安的是,每个人似乎都在说php的crypt()时说“ bcrypt”。
SLIQ

3
@Panique为什么?该算法称为bcryptcrypt公开了几个密码哈希,其中bcrypt对应于CRYPT_BLOWFISH常量。Bcrypt是目前受支持的最强大的算法,crypt它支持的其他几种算法也很弱。
CodesInChaos

34

编辑:2013.01.15-如果您的服务器支持它,请改用martinstoeckli的解决方案


每个人都想使事情变得更复杂。crypt()函数完成大部分工作。

function blowfishCrypt($password,$cost)
{
    $chars='./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    $salt=sprintf('$2y$%02d$',$cost);
//For PHP < PHP 5.3.7 use this instead
//    $salt=sprintf('$2a$%02d$',$cost);
    //Create a 22 character salt -edit- 2013.01.15 - replaced rand with mt_rand
    mt_srand();
    for($i=0;$i<22;$i++) $salt.=$chars[mt_rand(0,63)];
    return crypt($password,$salt);
}

例:

$hash=blowfishCrypt('password',10); //This creates the hash
$hash=blowfishCrypt('password',12); //This creates a more secure hash
if(crypt('password',$hash)==$hash){ /*ok*/ } //This checks a password

我知道这应该很明显,但是请不要使用“密码”作为您的密码。


3
盐的创建可以改进(使用操作系统的随机源),否则对我来说看起来不错。对于较新的PHP版本,最好使用2y代替2a
martinstoeckli 2013年

使用mcrypt_create_iv($size, MCRYPT_DEV_URANDOM)作为源为盐。
CodesInChaos

一会儿,我将仔细看一下mcrypt_create_iv(),如果没有别的什么可以稍微改善性能。
Jon Hulka 2013年

2
添加Base64编码并转换为自定义字母bcrypt用途。mcrypt_create_iv(17, MCRYPT_DEV_URANDOM)str_replace('+', '.', base64_encode($rawSalt))$salt = substr($salt, 0, 22);
CodesInChaos

1
@JonHulka-看一下PHP的兼容性包 [Line 127],这是一个简单的实现。
martinstoeckli

29

PHP 5.5版将内置对BCrypt,功能password_hash()和的支持password_verify()。实际上,这些只是函数的包装crypt(),可以使正确使用它变得更加容易。它负责安全随机盐的生成,并提供良好的默认值。

使用此功能的最简单方法是:

$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

此代码将使用BCrypt(algorithm 2y)对密码进行哈希处理,从OS随机源生成随机盐,并使用默认的cost参数(目前为10)。第二行检查用户输入的密码是否与已存储的哈希值匹配。

如果要更改cost参数,可以这样进行,将cost参数增加1,就可以将计算散列值所需的时间加倍:

$hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 11));

"cost"参数相反,最好省略该"salt"参数,因为该函数已经尽力创建了密码安全的盐。

对于PHP 5.3.7及更高版本,存在一个兼容包,该来自创建该password_hash()函数的同一作者。对于5.3.7之前的PHP版本,不支持crypt()with 2y和Unicode安全BCrypt算法。可以用代替它2a,这是早期PHP版本的最佳替代。


3
读完这篇文章后,我的第一个念头是“您如何储存所产生的盐”?在浏览文档之后,password_hash()函数最终生成了一个字符串,该字符串存储了加密方法,salt和所生成的哈希。因此,它只是将所需的所有内容存储在一个字符串中,以便password_verify()函数起作用。只是想提及这一点,因为这可能对其他人有帮助。
jzimmerman2011 2014年

@ jzimmerman2011-确实,在另一个答案中,我尝试用一​​个示例解释这种存储格式。
martinstoeckli 2014年

7

当前的想法:散列应该是最慢的,而不是最快的。这样可以抑制彩虹表攻击。

两者也相关,但是预防措施:攻击者永远不能无限制地访问您的登录屏幕。为防止这种情况,请执行以下操作:设置一个IP地址跟踪表,该表记录每次匹配以及URI。如果在任何五分钟的时间内有5次以上的登录尝试来自同一IP地址,请阻止并进行解释。第二种方法是像银行一样采用两层密码方案。在第二遍设置故障锁定可以提高安全性。

简介:通过使用耗时的哈希函数来降低攻击者的速度。另外,阻止对您的登录名的太多访问,并添加第二个密码层。


我认为他们认为攻击者已经设法通过其他方法窃取了我的数据库,并且现在正试图获取密码以便在Paypal上尝试使用它们。
Vilx- 2011年

4
到2012年已经过去了一半,这个答案仍然很奇怪,慢速哈希算法如何防止彩虹表攻击?我以为盐是随机字节范围的吗?我一直认为哈希算法的速度决定了它们可以在特定的时间内针对您从您那里获得的哈希发送多少次迭代。同样,永远也不会阻止用户登录失败,请相信我,您的用户会很烦,在某些网站上,我需要登录近5次,有时甚至需要登录五次以上,才能记住密码。同样,第二阶段的通行证也不起作用,但是可以使用手机代码进行两步身份验证。
Sammaye

1
@Sammaye我同意这一点。我在5次失败的登录尝试上设置了一个阻止块,然后将其迅速提高到7个,然后将其提高到10个(现在为20个)。没有普通用户应该进行20次失败的登录尝试,但是其登录级别足够低,可以轻松阻止暴力攻击
Bruce Aldridge

@BruceAldridge我个人认为,最好在7次登录失败并显示验证码而不是阻止之后使脚本暂停一段时间。封锁是非常激进的举动。
Sammaye 2012年

1
@Sammaye我同意永久块是不好的。我指的是随着尝试失败次数的增加而增加的临时块。
布鲁斯·奥尔德里奇

7

这是这个老问题的最新答案!

自5.5以来password_hash(),在PHP中哈希密码的正确方法是使用,而在验证密码的正确方法是使用password_verify(),在PHP 8.0中仍然如此。这些函数默认情况下使用bcrypt散列,但已添加了其他更强大的算法。您可以通过password_hash参数更改工作因数(实际上是加密的“强”程度)。

但是,尽管它仍然足够强大,但是bcrypt不再被认为是最先进的;一套更好的密码哈希算法已经到来,称为Argon2,具有Argon2i,Argon2d和Argon2id变体。(如描述他们之间的差别在这里):

Argon2有一个主要变体:Argon2id,还有两个补充变体:Argon2d和Argon2i。Argon2d使用取决于数据的内存访问,这使其适用于加密货币和工作量证明应用程序,而不会受到旁通道定时攻击的威胁。Argon2i使用与数据无关的内存访问,这对于密码哈希和基于密码的密钥派生而言是首选。Argon2id在内存上第一次迭代的前半部分充当Argon2i,其余部分则充当Argon2d,因此由于时间记忆的折衷,既提供了边通道攻击保护,又节省了蛮力成本。

PHP 7.2中添加了Argon2i支持,您可以这样请求它:

$hash = password_hash('mypassword', PASSWORD_ARGON2I);

在PHP 7.3中添加了Argon2id支持:

$hash = password_hash('mypassword', PASSWORD_ARGON2ID);

验证密码不需要更改,因为生成的哈希字符串包含有关创建密码时使用的算法,盐和工作因子的信息。

libsodium(在PHP 7.2中添加)非常独立(并且有些冗余),它还通过sodium_crypto_pwhash_str ()sodium_crypto_pwhash_str_verify()函数提供Argon2哈希,其工作方式与PHP内置函数大致相同。使用这些参数的可能原因之一是,有时PHP可能没有libargon2进行编译,这使得Argon2算法对于password_hash函数不可用。PHP 7.2及更高版本应始终启用libsodium,但可能未启用-但至少可以通过两种方式获得该算法。这是您可以使用libsodium创建Argon2id哈希的方法(即使在PHP 7.2中,否则它也缺少Argon2id支持)):

$hash = sodium_crypto_pwhash_str(
    'mypassword',
    SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
    SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
);

请注意,它不允许您手动指定盐。这是libsodium精神的一部分– 不允许用户将参数设置为可能危及安全性的值 –例如,没有什么阻止您将空的salt字符串传递给PHP password_hash函数的;libsodium不允许您做任何如此愚蠢的事情!



1

众所周知,将密码以明文形式存储在数据库中并不安全。bcrypt是一种哈希密码技术,用于建立密码安全性。bcrypt的惊人功能之一是它使我们免遭黑客攻击,因为密码以bcrypt形式存储,因此可用于保护密码免受黑客攻击。

password_hash()函数用于创建新的密码哈希。它使用了强大的哈希算法。password_hash()函数与crypt()函数非常兼容。因此,由crypt()创建的密码哈希可以与password_hash()一起使用,反之亦然。函数password_verify()和password_hash()只是函数crypt()的包装器,它们使准确使用它变得容易得多。

句法

string password_hash($password , $algo , $options)

password_hash()函数当前支持以下算法:

PASSWORD_DEFAULT PASSWORD_BCRYPT PASSWORD_ARGON2I PASSWORD_ARGON2ID

参数:该函数接受上述和以下所述的三个参数:

密码:它存储用户的密码。 algo:它是密码算法常量,它在表示密码散列发生时将要使用的算法而连续使用。 options:它是一个关联数组,其中包含选项。如果将其删除但不包括在内,则将使用随机盐,并且将使用默认成本。 返回 :成功时返回哈希密码,失败时返回False。

范例

Input : echo password_hash("GFG@123", PASSWORD_DEFAULT); Output : $2y$10$.vGA19Jh8YrwSJFDodbfoHJIOFH)DfhuofGv3Fykk1a

下面的程序说明了PHP中的password_hash()函数:

<?php echo password_hash("GFG@123", PASSWORD_DEFAULT); ?>

输出值

$2y$10$Z166W1fBdsLcXPVQVfPw/uRq1ueWMA6sLt9bmdUFz9AmOGLdM393G

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.