您在这里看到的不仅仅是密码哈希,还有很多关于这些字符串中包含的哈希的元数据。就 bcrypt 而言,整个字符串将被视为 bcrypt 哈希。以下是它包括的内容:
$ 是 bcrypt 中的分隔符。
$ 2a $ 是使用的 bcrypt 算法。
10美元是使用的成本因素。这就是为什么 bcrypt 在存储哈希方面非常受欢迎。每个散列都有与之相关的复杂性/成本,您可以将其视为计算机生成此散列所需的速度。这个数字当然是与计算机的速度相关的,所以随着这些年来计算机越来越快,生成成本为 10 的散列所花费的时间将越来越少。所以明年你将成本增加到 11,然后到 12... 13... 等等。这允许您未来的哈希值保持强大,同时保持旧哈希值仍然有效。请注意,如果不重新散列原始字符串,就无法更改散列的成本。
$QyrjMQf... 是盐和哈希的组合。这是一个 base64 编码的字符串。
前 22 个字符是盐。
剩余的字符是与 2a 算法一起使用时的哈希值、10 的成本和给定的盐。使用盐的原因是攻击者无法预先计算 bcrypt 哈希值以避免支付生成它们的成本。
实际上,这是您最初问题的答案:哈希值不同的原因是因为如果它们相同,您就会知道,无论何时您看到 bcrypt 字符串$2a$10$QyrjMQfjgGIb4ymtdKQXI.WObnWK0/CzR6yfb6tlGJy0CsVWY0GzO
,您都会知道密码是abcd
. 因此,您可以只扫描一个哈希数据库,并通过查找该哈希快速找到所有使用 abcd 密码的用户。
你不能用 bcrypt 做到这一点,因为$2a$10$dQSPyeQmZCzVUOXQ3rGtZONX6pwvnKSBRmsLnq1t1CsvdOTAMQlem
is also abcd
. 还有很多很多很多的哈希将是bcrypt('abcd')
. 这使得扫描数据库以查找 abcd 密码几乎是不可能的。