我们正在遵循非常标准的用户ID /密码检查。我们将散列密码存储在db中。当用户输入凭证时,我们对输入的密码进行哈希处理,然后与数据库进行比较。如果匹配,则用户进行身份验证。
现在这个负载测试下的登录过程大大减慢了,所以我被要求查看它。 VS 2013 Profiler指出散列方法是一条热门途径。看看有问题的方法,我们循环遍历散列过程??
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循环连接到他们的性能问题之前,我想看看这样的重组是否确实增加了安全性?
据我所知,单个哈希实际上是不可能反转的,为什么浪费周期重复这个过程?
思想?
修改
添加了GenerateHash:
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);
}
答案 0 :(得分:3)
这种称为&#34;拉伸&#34;的重复散列技术用于使暴力攻击更加困难。如果哈希密码需要0.1秒(由于重复),那么攻击者最多每秒可以尝试10个密码来查找匹配。如果你加快散列过程所需的时间需要一微秒,那么攻击者可以每秒测试一百万个密码。
您需要平衡速度与安全性。用户登录只需要足够快以满足用户,因此0.1到0.5秒可能是可以接受的。
如果您的服务器过载,则获得更快的处理器,或购买专用的散列服务器。这将比数据泄露的法律后果便宜很多。
答案 1 :(得分:3)
重复哈希操作对于保护密码身份验证至关重要,但是你做错了,因此确实浪费CPU来实现任何目标。
您应该使用像PBKDF2这样的算法,在每轮散列中包含密码,以保留密码的所有不可预测性。 bcrypt,特别是scrypt也是不错的选择。
此外,一千轮还不够;为了防止脱机字典攻击,即使在攻击者的专用密码测试硬件上执行,您也需要散列操作相对较慢。挑选一轮素数是毫无意义的傻瓜。轮数将取决于您选择的算法,但对于具有SHA-256的PBKDF2,介于10,000到100,000轮之间应提供合理的安全级别。
需要一种缓慢的算法来防止获取哈希的攻击者快速尝试许多不同的密码来查看哪个产生相同的哈希值。确实,安全散列不可能反转,但它不会停止猜测,并且攻击者擅长优先考虑他们的猜测,首先尝试最可能的密码。重复哈希是提供这种必要的缓慢的原因。
StackOverflow已经多次讨论过这个问题。我推荐您a previous answer了解更多背景信息。
在C#中,您可以使用Rfc2898DeriveBytes
安全地执行密码哈希。您可以将Base-64中的派生密钥编码为存储为字符串,或者实际将其用作加密密钥来加密已知的纯文本,如bcrypt算法。您会注意到Rfc2898DeriveBytes
使用&#34; salt&#34;,I discuss elsewhere;您需要将此值与哈希值一起存储,以便稍后执行身份验证。