我正在使用rails,我注意到我的password_digest对于2个用户而言是不同的,除了密码摘要之外的所有其他字段都不同。但我用两个相同的密码“abcd”..
它最终产生了这两个不同的哈希
$2a$10$QyrjMQfjgGIb4ymtdKQXI.WObnWK0/CzR6yfb6tlGJy0CsVWY0GzO
$2a$10$dQSPyeQmZCzVUOXQ3rGtZONX6pwvnKSBRmsLnq1t1CsvdOTAMQlem
我认为bcrypt gem只根据密码字段生成哈希值!我错了吗? 谢谢:))
答案 0 :(得分:19)
您在这里看到的不仅仅是密码哈希,还有很多关于这些字符串中包含的哈希的元数据。就bcrypt而言,整个字符串将被视为bcrypt哈希。以下是它的内容:
$是bcrypt中的分隔符。
$ 2a $是使用的bcrypt算法。
$ 10 $是使用的成本因素。这就是为什么bcrypt非常适合存储哈希的原因。每个哈希都有与之相关的复杂性/成本,您可以将其视为计算机生成此哈希的速度。这个数字当然与计算机的速度有关,因此随着计算机越来越快,多年来生成一个成本为10的哈希所需的时间越来越少。因此,明年你将成本增加到11,那么到12 ...... 13 ......等等。这样可以使您的未来哈希值保持强劲,同时保持旧哈希值仍然有效。请注意,如果不重新散列原始字符串,则无法更改散列的成本。
$ QyrjMQf ...是salt和hash的组合。这是base64编码的字符串。
前22个字符是盐。
剩余的字符是与2a算法一起使用时的散列,成本为10,以及给定的盐。盐的原因是攻击者不能预先计算bcrypt哈希值以避免支付生成它们的成本。
实际上这是你原来问题的答案:哈希的不同之处在于,如果它们是相同的,你就会知道,只要你看到bcrypt字符串$2a$10$QyrjMQfjgGIb4ymtdKQXI.WObnWK0/CzR6yfb6tlGJy0CsVWY0GzO
,你就会知道密码是{ {1}}。因此,您只需扫描哈希数据库,并通过查找该哈希值快速查找具有abcd密码的所有用户。
您不能使用bcrypt执行此操作,因为abcd
也是$2a$10$dQSPyeQmZCzVUOXQ3rGtZONX6pwvnKSBRmsLnq1t1CsvdOTAMQlem
。而且abcd
会产生许多更多的哈希值。这使得扫描数据库的abcd密码几乎不可能。
答案 1 :(得分:2)
bcrypt
将salt存储在密码哈希中。
这是两个不同的哈希,密码相同,有两种不同的盐。
验证密码时,bcrypt将从哈希字段读取salt,然后使用该盐重新计算哈希值。