Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 基于Unicode密码的哈希_.net_Unicode_Hash_Passwords - Fatal编程技术网

.net 基于Unicode密码的哈希

.net 基于Unicode密码的哈希,.net,unicode,hash,passwords,.net,Unicode,Hash,Passwords,我正在为我的.NET应用程序编写一个密码salt/hash过程,主要遵循本文的指南: 基本上,计算盐哈希的代码如下: public string ComputeSaltedHash(string password, byte[] salt) { // Get password ASCII text as bytes: byte[] passwordBytes = System.Text.Encoding.ASCII.GetBytes(password); // Ap

我正在为我的.NET应用程序编写一个密码salt/hash过程,主要遵循本文的指南:

基本上,计算盐哈希的代码如下:

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调用会崩溃

这是一个合理的问题,还是可以?

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

我建议:

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

    • 将第一个引用更改为
      Unicode
      UTF-8
      就足够了。但是,您可能希望对输入进行规范化,以考虑各种输入重音等方式。

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

      return BitConverter.ToString(computedHash)
      

      <强>您可能要考虑的是密码增强。< /强> BR> SHA1非常快,有时太快了。一个系统将能够每秒计算数百万个哈希。该速度允许攻击者尝试常见的单词词典攻击(包括大小写差异)和数字扩展。SHA1的速度允许在合理的时间内完成一个大的字典空间,打破大多数用户的密码

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

      您可以滚动您自己的,但是.net framework公开了一个类来实现这一点: System.Security.Cryptography.Rfc2898DeriveBytes

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


      好的观点。这个问题不仅仅与Unicode实现有关。现有的ASCII实现也存在同样的缺陷。感谢您对ASCII编码的深刻评论。这让我想起Eric Lippert的一篇文章,其寓意是“不要使用你不完全理解的密码系统”()。附言-刚刚收到我的C#Depth 2ed电子书,期待与它共度时光!