Unicode密码的哈希处理

6
我正在为我的.NET应用编写一个密码盐/哈希过程,主要遵循这篇文章的指南: http://www.aspheute.com/english/20040105.asp 基本上,计算盐哈希的代码如下:
public string ComputeSaltedHash(string password, byte[] salt) {

    // Get password ASCII text as bytes:
    byte[] passwordBytes = System.Text.Encoding.ASCII.GetBytes(password);

    // Append the two arrays
    byte[] toHash = new byte[passwordBytes.Length + salt.Length];
    Array.Copy(passwordBytes, 0, toHash, 0, passwordBytes.Length);
    Array.Copy(salt, 0, toHash, passwordBytes.Length, salt.Length);

    byte[] computedHash = SHA1.Create().ComputeHash(toHash);

    // Return as an ASCII string
    return System.Text.Encoding.ASCII.GetString(computedHash);
}

然而,我希望允许用户在密码中使用Unicode字符,如果他们愿意的话。(这似乎是一个好主意;有人能想到不允许的原因吗?)

然而,我对Unicode的工作方式并不是很了解,我担心如果我只是将System.Text.Encoding.ASCII的两个引用都更改为System.Text.Encoding.Unicode,哈希算法可能会产生一些无法形成有效Unicode字符的字节组合,从而使GetString调用出现问题。

这是一个有效的担忧吗,还是没事?

3个回答

12

你不应该使用任何普通编码方式将任意二进制数据转换回字符串。这不是已编码的文本——它只是一系列字节。不要试图将其解释为“正常”文本。原始密码是否包含任何非ASCII字符对此无关——你当前的代码存在问题。(基于这一点,我会对链接的文章持怀疑态度。)

我建议:

  • 使用Encoding.UTF8获取密码的字节。这将允许密码包含任何Unicode字符。Encoding.Unicode在这里也可以。
  • 使用Convert.ToBase64String将计算出的哈希值转换回文本。Base64专门设计用于在ASCII字符集内表示不透明的二进制数据。

好观点。问题不仅与Unicode实现有关,现有的ASCII实现同样存在缺陷。 - Gerald Davis
感谢您对ASCII编码的深入评论。这让我想起了Eric Lippert的一篇文章,其道德是“不要使用您不完全理解的加密系统”(http://blogs.msdn.com/b/ericlippert/archive/2009/12/14/use-the-right-tool-for-the-job.aspx)。附言:刚刚收到我的C#深度2版电子书,期待花些时间阅读它! - Hank

2

只需将第一个引用更改为UnicodeUTF-8即可。但是,您可能希望规范化输入,以考虑各种输入重音符号等的方式。


0

我更喜欢Jon的解决方案,但另一个选择是将原始十六进制值存储为字符串。请用以下代码替换你的最后一行:

return BitConverter.ToString(computedHash)

在编程中需要考虑的一件事是密码强化。
SHA1 是非常快的,有时候速度太快了。一个系统可以每秒计算成百万个哈希值。这种速度允许攻击者尝试使用通用字典攻击(包括大小写变换)和数字扩展。SHA1 的速度允许在合理的时间内完成广泛的字典空间,破解大多数用户的密码。

加强密码的一种方法是多次哈希它,这增加了哈希的 CPU 要求。将 SHA1 哈希的输出作为第二轮的输入传递。至少要做1000次。这会减慢您和攻击者的哈希计算速度。对于您的用户,它会延迟访问,但只是微不足道的时间;该例程将在0.01秒而不是0.0001秒内返回。但是对于暴力攻击,您已经将执行时间增加了1000倍。

您可以自己编写代码,但 .NET 框架提供了一个专门用于此目的的类:System.Security.Cryptography.Rfc2898DeriveBytes

RFC2898 使用 SHA1 算法,并接受明文、盐和迭代次数。它可以输出可变长度的密钥。

http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接