Ruby BCrypt似乎在撒盐/散列... ...错了吗?

时间:2019-06-21 04:19:34

标签: ruby authentication passwords bcrypt salt

我一直在红宝石应用程序中创建咸密码,我认为这是标准方式:

password_salt = BCrypt::Engine.generate_salt
password_hash = BCrypt::Engine.hash_secret(params[:pword], password_salt)

但是在检查一个测试用例时,盐似乎只是被加在哈希密码之前:

Fishy looking screencap of user table.

现在,据我所知,盐应该在散列之前被连接到密码上,以将密码推出任何预先计算的查找表,彩虹表等可以容纳的大小范围。曾经包括。关键是,如果有人获得了您的用户数据库,他们仍然无法使用查找表来破解密码。如果在哈希运算之后将盐加到密码前,并且黑客已经下载了用户表,则它不会做任何保护密码的操作。黑客只需将盐从前面剪下来,拿回原来的哈希值,然后在哈希表上运行彩虹表,就好像它们从未被添加盐一样。

这是否像看起来那样失败?这是我的代码中的问题吗?还是由于我需要继续阅读的原因而使它工作正常且安全吗? (请链接。)

2 个答案:

答案 0 :(得分:4)

1)盐对于验证是必需的,因此必须与哈希密文一起存储。无论是数据库中的两个字段还是一个模糊的字符串,都是无关紧要的。

2)一盐=一彩虹桌。当然,攻击者可以为您的盐生成一个新的彩虹表;但是,由于建立彩虹表的时间基本上等于尝试彩虹表要涵盖的所有密码的时间,因此只要您不重复使用盐,这并不是一个弱点。


rainbow表的用例是它允许您一次计算一次,然后快速测试多个密码。彩虹表通常会覆盖所有密码,直到一定长度,或者至少有一定限制(例如,使用某些字母或使用某些词汇表)。假设您有一个彩虹表,该表涵盖了最多8个字符的所有密码。因此,如果有人使用密码“ password”,则彩虹表将知道其哈希形式是什么(例如,“ WASSPORD”-使用大写字母表示密文,使用小写字母表示纯文本,以提高示例的可读性),然后您可以在彩虹表,很快看到密码是“密码”。

但是,说您有盐“花生”。密码变为“ peanutspassword”,然后如果对其进行加密,可以说您得到“ WASSUPMYCRACKER”。 Ruby将打印“ peanutsWASSUPMYCRACKER”作为加盐的哈希值。在验证时,将“ peanutsWASSUPMYCRACKER”分为“ peanuts”(盐)和“ WASSUPMYCRACKER”(哈希);将“ peanuts”附加到用户的“ password”输入中以形成“ peanutspassword”,然后再次对其进行加密-您将获得“ WASSUPMYCRACKER”,这是一个匹配项,并且用户已登录。但是请注意,“ peanutspassword”较长最多8个字符,并且不会出现在最多8个字符的彩虹表中。

现在,您可以通过使用与原始彩虹表相同的字典,在“花生”之前添加并对其进行加密,来生成一个“花生”彩虹表,但是通常比暴力破解密码(“花生“ +” a“?”花生“ +” aardvark“?...),因为至少当您用蛮力攻击时,找到正确的密码就会停止。

但是,如果您知道某个应用程序始终使用“花生”作为盐,则可以制作一个“花生”彩虹表,该应用程序是烤面包,其所有者陷入了真正的果酱。

tl; dr:盐可以公开使用;只是不能重复使用。


编辑:您似乎对Ruby只是将盐粘贴到无盐明文的哈希值上有一种印象。如果这样做,那么对于相同的明文,无论盐如何,结果的后尾(密文)都是相同的。很容易看出来这不是它的工作原理:

3.times { puts BCrypt::Engine.hash_secret("password", BCrypt::Engine.generate_salt) }
# $2a$10$jxUToaac5UUzVRH9SnllKe52W1JMLu5tm0LwyrZ4x4e75O1FCn9Ea
# $2a$10$oBs3TyhgR/r12.cz2kdzh.O9WHVZifDPqTEg0.hGOMn7Befv.8hSy
# $2a$10$8rfQA5nzCZ74DwNrmhAhdOmoQOVhJnBfh0ikiOB0W7ZptwsLPGUwi

随着盐的变化,密文发生变化。因此,您不能“只是将盐从表皮上剪下来,取回原始哈希,然后在哈希表上运行彩虹表,就好像它们从未被加盐一样。”

答案 1 :(得分:0)

我在Python中遇到了同样的问题:

passw = "qay123"
salt = bcrypt.gensalt(14)
hashedpw = bcrypt.hashpw(passw, salt)
print salt
print hashedpw

输出:

$2b$14$fG3IoYLeIaf6gxZTHVR7eO  <--- salt
$2b$14$fG3IoYLeIaf6gxZTHVR7eOVOC08a77IDOiu4At4FKKecw1xBYKXyG <-- salt + hashedpw

因此,hashpw函数仅将盐值与不安全的哈希值连接在一起,因为黑客可以在位置30分割salt + hashpw 因此消除了盐分。

对于彩虹桌子,黑客必须能够读取哈希,因此切割不是问题。他唯一可能遇到的问题是盐的长度会发生变化。

我的想法是,您遵循自己的想法,并且使用bscrypt似乎不是故意的。