Rehashing a hash (SHA512)
我们正在进行标准的用户ID/密码检查。我们将哈希密码存储在数据库中。当用户输入凭据时,我们散列输入的密码,然后与数据库的密码进行比较。如果它们匹配,则对用户进行身份验证。
现在,负载测试下的这个登录过程大大减慢了,所以我被要求查看它。vs 2013 profiler指出散列方法是一个热门路径。看看有问题的方法,我们是在哈希过程中循环??
1 2 3 4 5 6 7 8 9 10 11 | private const int totalHashCount = 1723; public string CreateHash(string salt, string password, int securityIndex) { string hashedPass = this.GenerateHashString(salt + password, securityIndex); for (int i = 1; i <= totalHashCount; i++) { hashedPass = this.GenerateHashString(hashedPass, securityIndex); } return hashedPass; } |
我去找开发人员,他说客户的安全团队希望我们重新刷新哈希表,并做一些大于1000的素数……他提供了电子邮件作为文档。
现在我不是一个密码专家,我们和客户关系很好,所以在我去找他们并将这个Rehash循环与他们的性能问题联系起来之前,我想看看这样的Rehash是否确实提高了安全性?
据我所知,一个哈希实际上是不可能反转的,那么为什么要浪费循环来重复这个过程呢?
思想?
编辑
新增发电灰:
1 2 3 4 5 6 7 8 9 10 | protected internal string GenerateHashString(string textToHash, int securityIndex = 0) { UnicodeEncoding uEncode = new UnicodeEncoding(); SHA512Managed sha = new SHA512Managed(); byte[] bytVal = uEncode.GetBytes(textToHash + hashIntPool[securityIndex].ToString()); byte[] hashVal = sha.ComputeHash(bytVal); return Convert.ToBase64String(hashVal); } |
号
重复散列操作对于保护密码身份验证是必要的,但是您做的不对,因此确实会浪费CPU而一无所获。
您应该使用像pbkdf2这样的算法,在每一轮哈希运算中都包含密码,以便保留密码的所有不可预测性。Bcrypt尤其是Scrypt也是不错的选择。
此外,一千回合还不够;为了防止离线字典攻击,即使在攻击者专用的密码测试硬件上执行哈希操作,您也需要使哈希操作相对缓慢。选择一个质数的回合是毫无意义的胡言乱语。轮数将取决于您选择的算法,但是对于带有sha-256的pbkdf2,大约10000到100000轮应该提供合理的安全级别。
为了防止获得哈希的攻击者快速尝试许多不同的密码,以查看哪个密码产生相同的哈希,需要使用慢速算法。确实,安全散列不可能反转,但它不会停止猜测,攻击者擅长将猜测的优先级设置为先尝试最可能的密码。哈希的重复就是提供这种必要的缓慢性的原因。
在StackOverflow上已经讨论过很多次了。我建议你参考前面的答案了解更多背景。
在C中,可以使用
这种被称为"拉伸"的重复散列技术被用来使暴力攻击更加困难。如果散列密码需要0.1秒(由于重复),那么攻击者最多可以每秒尝试10个密码来找到匹配的密码。如果您加快了散列过程,使它需要一微秒,那么攻击者可以每秒测试一百万个密码。
你需要平衡速度和安全。用户登录只需要足够快来满足用户的需求,因此0.1到0.5秒可能是可以接受的。
如果你的服务器超载,那么就买一个更快的处理器,或者买一个专用的哈希服务器。这比数据泄露的法律后果要便宜得多。