2010-11-16 112 views
6

我正在写一个密码盐/哈希程序为本人.NET应用程序,这篇文章的导向主要是以下几点: http://www.aspheute.com/english/20040105.asp哈希Unicode的密码

基本上用于计算哈希腌制的代码是这样的:

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的调用将吓坏了。

这是一个有效的关注,还是会好吗?

回答

12

你不应该使用任何正常编码,从任意的二进制数据转换回字符串。它不是编码文本 - 它只是一个字节序列。不要试图将它解释为“正常”文本。原始密码是否包含任何非ASCII字符与此无关 - 您的当前代码已损坏。 (我会像对待一个大剂量的怀疑只是在此基础上的链接的文章)。

我建议:

  • 使用Encoding.UTF8摆脱密码字节。这将允许密码包含任何Unicode字符。 Encoding.Unicode也可以。
  • 使用Convert.ToBase64String将计算出的散列值转换回文本。 Base64专门用于表示ASCII字符集中文本中的不透明二进制数据。
+0

好一点。这个问题与Unicode的实现无关。现有的ASCII实现同样存在缺陷。 – 2010-11-16 16:15:34

+0

感谢您对ASCII编码的深刻见解。这让我想起了Eric Lippert的一篇文章,其道德是“不要使用你不完全了解的密码系统”(http://blogs.msdn.com/b/ericlippert/archive/2009/12/ 14 /使用最右工具换的-job.aspx)。附: - 刚刚收到我的C#深入2ED电子书,期待花一些时间与它! – 2010-11-16 16:40:42

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 algorith并接受纯文本,盐和迭代次数。它可以输出一个可变长度的密钥。

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