数据库泄露后,password_verify() 可以用来识别密码吗?

信息安全 哈希 php
2021-09-12 22:04:54

我是 PHP 和密码哈希的新手。我按照@Safe Password Hashing提供的说明在存储之前对我的用户密码进行哈希处理。

我的问题是:

  1. PHP 推荐password_hash()方法作为首选的安全散列方式。如果发生数据库泄露,黑客不会使用password_verify()和识别密码而不是使用彩虹查找表吗?

  2. 如果是这样,我应该采取什么方法来弥补这个安全漏洞?

4个回答

password_verify()有两个参数:一个字符串,你想检查它是否是正确的密码,以及你之前用 计算的值password_hash(),你大概存储在数据库中的某个地方左右。

一个典型的应用可能是:

<?php
$hash = password_hash('my-secret', PASSWORD_DEFAULT);
// normally you would save the hash somewhere, but we'll just continue in this example

$check_a = 'other-secret';
$check_b = 'my-secret';
if (password_verify($check_a, $hash))
   echo 'Check A was the original password: ' . $check_a;
if (password_verify($check_b, $hash))
   echo 'Check B was the original password: ' . $check_b;

输出将是:

Check B was the original password: my-secret

如果您想从 计算的哈希中获取原始密码password_hash(),您需要尝试所有可能性 - 这就是本示例所显示的内容。因为 的架构password_hash(),找这样的密码要花很长时间,所以不值得。

另请注意,来自password_hash()文档

PASSWORD_DEFAULT- 使用 bcrypt 算法(默认为 PHP 5.5.0)。请注意,此常量旨在随着 PHP 中添加新的和更强大的算法而随时间而变化。因此,使用此标识符的结果长度可能会随时间而变化。因此,建议将结果存储在可以扩展超过 60 个字符的数据库列中(255 个字符将是一个不错的选择)。

该算法旨在随时间变化,以保持安全,并且使用更快的计算机无法通过蛮力找到密码(假设您服务器上的 PHP 安装是最新的)

在任何情况下,散列都是单向的:你不能把它转过来。您只能通过计算哈希验证给定的密码一个,并检查它是否是相同的。

password_verify()只会确认给定的密码是否与给定的哈希匹配。它仍然需要输入,彩虹表是一种为输入生成可能的密码的方法。但是,如果您生成推荐大小的盐值,它将有助于防止彩虹表攻击。

您可以通过阅读如何安全地散列密码找到更多关于使用散列和盐正确保护密码的信息。

由于哈希函数确实很难反转,因此您不能简单地通过提供哈希来推断解决方案。攻击者可以开发一种策略来找到与您存储在数据库中的密码摘要匹配的密码的可能性可以忽略不计。不知道 PHP 的默认散列方法是什么,但所有现代散列算法都是抗冲突的,所以不用担心。

真正获得真实密码的唯一方法是对散列密码使用暴力攻击,因为默认的 php 密码散列算法是 bcrypt,这将花费大量时间。