代码之家  ›  专栏  ›  技术社区  ›  Hank

Unicode密码上的哈希

  •  6
  • Hank  · 技术社区  · 14 年前

    我正在为我的.NET应用程序编写密码salt/hash过程,主要遵循本文的指导: 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 回复  |  直到 14 年前
        1
  •  12
  •   Jon Skeet    14 年前

    你不应该使用 任何 从任意二进制数据转换回字符串的普通编码。它不是编码文本-它只是一个字节序列。不要试图将其解释为“普通”文本。原始密码是否包含任何非ASCII字符与此无关-您当前的代码被破坏。(我只是基于这个理由,对这篇文章有很大的怀疑。)

    我建议:

    • 使用 Encoding.UTF8 从密码中获取字节。这将允许密码包含任何Unicode字符。 Encoding.Unicode 在这里也可以。
    • 使用 Convert.ToBase64String 从计算的哈希转换回文本。base64是专门设计用来在ASCII字符集中以文本形式表示不透明的二进制数据。
        2
  •  2
  •   Joey    14 年前

    将第一个引用改为 Unicode UTF-8 . 但是,您可能希望规范化输入,以说明输入重音符号等的各种方式。

        3
  •  0
  •   Gerald Davis    14 年前

    我更喜欢jon解决方案,但另一个选择是将原始十六进制存储为字符串。将最后一行替换为:

    return BitConverter.ToString(computedHash)
    

    您可能需要考虑的一件事是加强密码。
    sha1非常快,有时太快。一个系统将能够每秒计算几百万个哈希。该速度允许攻击者尝试常见的字典攻击(包括大小写的差异)和数字扩展。sha1的速度允许在合理的时间内完成宽字典空间,从而破坏大多数用户的密码。

    加强密码的方法是多次散列它,这会增加散列的CPU需求。获取sha1散列的输出并将其作为第二轮的输入传递。至少做1000次。这会降低您和攻击者的哈希计算速度。对于您的用户,它将访问延迟很短的时间;该例程将在0.01秒而不是0.0001秒后返回。但是对于蛮力攻击,执行时间增加了1000倍。

    您可以滚动自己的.NET框架,但.NET框架会公开一个类来执行以下操作: system.security.cryptography.rfc2898派生字节

    RFC2898使用sha1算法,接受纯文本、salt和迭代次数。它可以输出可变长度的键。

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