随着最近(例如LinkedIn)关于密码的讨论,我正在研究密码哈希实现。喝完两杯咖啡和早上读书后,我不再是一个密码学家了。我真的不想假装自己。
使用整数唯一用户ID失败是否有效? (crypt()只使用16位?)
如果我只是一遍又一遍地在哈希上运行sha256(),直到一秒钟用完就能击败蛮力攻击?
如果我必须问这些问题我应该使用bcrypt吗?
目标很简单,如果我的用户的哈希密码泄露了他们:
我读到的第一个问题是哈希计算必须是昂贵的 - 例如,计算一两秒或者需要一点或内存(以阻止硬件解密)。
bcrypt内置了这个,如果我理解正确的话,scrypt更具有前瞻性,并且包含最低内存使用要求。
但是,通过“重新散布”sha256()的结果,根据需要多次使用几秒钟,然后使用哈希值存储最终循环计数以便稍后检查提供的内容,这是一种同样有效的方法来节省时间密码?
对于#2,为每个密码使用唯一的盐很重要。目前尚不清楚的是盐必须是随机的(或大的)。如果目标是避免使用“mypassword”作为密码的每个人拥有相同的哈希值,那么仅仅这样做是不够的?:
hash = sha256_hex( unique_user_id + user_supplied_password );
甚至是这个,虽然我不确定它能给我买什么:
hash = sha256_hex( sha256( unique_user_id ) + user_supplied_password );
使用用户ID可以看到的唯一好处,除了我知道它是唯一的,是避免必须与哈希一起保存盐。没有多大优势。使用用户的ID作为盐是否存在真正的问题?它没有完成#2吗?
我假设如果有人可以窃取我的用户的哈希密码,那么我必须假设他们可以得到他们想要的任何东西 - 包括生成哈希的源代码。那么,在散列之前向密码添加额外的随机字符串(相同的字符串)是否有任何好处?那就是:
# app_wide_string = one-time generated, random 64 7-bit *character* string.
hash = sha256_hex( unique_user_id + app_wide_string + user_supplied_password );
我已经看到了这个建议,但我不明白我从中获得了多于每用户盐。如果有人想强行进行攻击,他们会知道“app_wide_string”并在运行字典攻击时使用它,对吗?
如上所述,是否有充分的理由使用bcrypt滚动我自己?也许我问这些问题的理由足够了?
顺便说一下 - 我只是计算了我现有的散列函数和我的笔记本电脑,我每秒可以生成大约7000个哈希值。不太经常建议的一两秒钟。
一些相关链接:
using sha256 as hashing and salting with user's ID
答案 0 :(得分:8)
Bcrypt很棒,因为你可以将工作因子从4调到31,每个增量都会产生一个指数所需的时间,我实际上已经绘制了它,工作因子为14,它已经超过了一秒,所以当计算机得到你只需要更改一个参数就可以越来越快,当然也要更新你的密码哈希......
我对bcrypt的主要关注是,如果工作因子设置为高,那么当多个用户尝试登录时,它可能会使系统超载,因此您可以根据并发登录的数量和资源来调整它。你的系统......
盐仍然是必需的,它们的主要目的是阻止离线攻击,如果盐空间很大,那么对手将无法生成查找表,64位盐似乎有点低, bcrypt有128位盐加上工作因素对离线攻击提出了相当大的挑战......是的,每个密码的盐应该是随机的,bcrypt会为你生成一个,如果你为每个密码使用相同的盐那么你已经让对手更难以使用在线攻击来压缩所有密码。
如果你已经正确设置了工作因素,那么Bcrypt对网络攻击真的很感兴趣,因为即使我得到了哈希值,也就是说如果'对手'获得了哈希值,那么工作因素会让人感到非常痛苦。整个字典,需要多天,如果密码不在字典中,那么我真的遇到麻烦导致暴力攻击将是史诗般的,bcrypt的密码位空间虽然有限但相当大:)Sha256现在可能需要一些时间,但最终计算机会变得越来越快,攻击起来也相当容易,unix家伙认为地穴是如此之慢,它永远不会是一个问题,今天我已经在几秒钟内完成了在线攻击,在几天内完成了线下攻击,在几周内进行了暴力攻击(通过整个密码位空间)......
答案 1 :(得分:0)
使用整数唯一用户ID是否会失败? (crypt()只使用16位?)
您通常使用随机生成的salt,然后将该哈希与加密密码一起存储。攻击者也可以访问盐并不重要 - 它的目的是阻止使用查找表,从而迫使攻击者单独强制每个哈希值。
crypt
只将salt和hash存储到一个字符串中,同时使用algoritm。