加密密码

11

我读过许多问题,建议将密码进行哈希处理并存储在数据库中。

当用户登录时,您使用所存储的信息哈希提供的密码。

我不明白的是这怎么可能起作用?因为两个字符串可能会哈希成相同的值 - 不太可能但绝对有可能。

有人可以帮助我吗?

编辑:有人能给出碰撞可能性的统计数据吗?


我在我的答案中提到了生日攻击: http://en.wikipedia.org/wiki/Birthday_attack它会根据尝试次数和可能哈希值的数量(基于位数)给出碰撞的可能性。这是一种暴力攻击。如果哈希可以被“破解”,那么可能性会更高。 - Vanwaril
https://dev59.com/CHRB5IYBdhLWcg3wc3E0 - erickson
你可能会发现我关于这个主题的一系列文章很有趣。http://blogs.msdn.com/ericlippert/archive/tags/Salt/default.aspx - Eric Lippert
一个用于此的库:http://encrypto.codeplex.com/ - Omu
17个回答

24

您不应该以明文形式存储密码,因为您的数据库管理员不应该有访问客户密码的权限。

对密码进行哈希处理可以防止数据库管理员查看密码。

即使存在哈希碰撞的非常小的几率,这也不是问题,因为在锁定账户之前,这并不会显著增加某人尝试暴力破解客户密码的成功率。

附注:在哈希处理之前对密码进行盐值处理是一个好习惯,这样如果黑客以某种方式访问了密码表,则更难以使用彩虹表等手段进行暴力破解。


6
为了最小化针对多个密码的暴力攻击风险,您还应该给它们加盐。 - Joey
7
密码本身没有太多的特点;因此需要始终对其进行加盐处理。 - user1228
2
一点辣椒会增加一些味道,我觉得。 - Wim
3
想要指出的是,Hash(哈希) 是一种单向函数,而 encryption(加密) 意味着拥有正确密钥的人可以解密原始密码。哈希用于密码检查最佳,发送安全的 HTML 网页时需要加密。 - Rob Fonseca-Ensor
考虑到暴力攻击,如果多次登录失败的尝试以极快的速度进行,这表明可能正在遭受攻击,因此超时多个失败的尝试是一个好主意。 - jamesmillerio

10

两个字符串可以哈希到相同的值 - 不太可能但绝对可能

是的,但如果哈希足够大并且质量良好,那么不必担心。用口语来说:每个应用程序用户同时被雷击的可能性不大,但绝对可能发生。你会为此而担心吗?


10
太好了,现在又有一件要担心的事情。谢谢。 - badideas
你必须将风险乘以后果。如果系统管理员(或黑客)与用户使用相同的密码,则他们将看到它们的哈希值和因此密码相同,并且将能够作为该用户登录。如果您正在构建银行网站,则这将成为一个问题。 - Rob Fonseca-Ensor
@Rob:这就是为什么你要添加随机盐的原因。不仅两个相同密码的哈希值会不同,而且它们也更难破解。 - SF.
@SF 嗯,那正是我试图倡导的内容 :$ - Rob Fonseca-Ensor

5
即使两个字符串可以散列到相同的值(它们肯定会,因为可能值的空间比哈希的空间大得多),但要找到这样的字符串对仍然不是很容易(前提是您使用强哈希函数)。
因此,如果攻击者想要以其他人的身份登录而不知道他的密码,则必须找到具有相同哈希的密码,这应该与找到密码一样困难(哈希函数的不可逆性是一种基本属性)。
如果您想在.NET中使用哈希,请尝试类似于以下内容:
    public static string ComputeHash(string plaintext)
    {
        HashAlgorithm mhash = new SHA1CryptoServiceProvider();
        byte[] bytValue = Encoding.UTF8.GetBytes(plaintext);
        byte[] bytHash = mhash.ComputeHash(bytValue);
        mhash.Clear();
        return Convert.ToBase64String(bytHash);
    }

4
您所提到的是“碰撞漏洞”。但是,首先需要了解一些背景知识。
如果您存储未加密的密码,那么这是一个安全漏洞,正如您可能已经猜到并且Sam建议的那样。但是,您可以使用经过验证的算法来降低此可能性。您绝对不应该尝试发明自己的算法(因为您似乎不是算法开发人员)。
我通常使用MD5,它在诸如MySQL之类的数据库中可用。这样,您还可以将检查嵌入到数据库查询中。
现在,不幸的是,MD5不是碰撞抗性的。但是,发生碰撞的机会非常小。您可以在论坛上找到其他建议。我知道SHA-2是其中一种可能性,但我不知道在应用程序中使用它有多容易。

碰撞漏洞是指发现两条信息具有相同的哈希值,其中一条无害,另一条恶意。您能解释一下碰撞漏洞与用户关于密码的问题有何关系吗?因为我没有跟上您的思路。 - Eric Lippert
对我来说,这个问题的翻译是“两个不同的字符串是否可以创建相同的哈希值”。最近我发现在MD5中是可能的。现在,其他用户指出你不需要让密码唯一。但在某些领域(比如我的当前领域),你不输入用户ID,所以密码应该是唯一的。在这种情况下,避免使用具有碰撞漏洞的哈希函数。实际上,碰撞的机会微乎其微,MD5仍然可以在99.99%的情况下工作。这比原始答案更有意义吗? - Tanmay

3

"MyAwesomePassword1"和"@@#ngt0n8$!!~~~09||{2`=&-[kla2%!Bq"可能会哈希成相同的值,这并不是一种安全漏洞。


2
您可以说“绝对可能”是指它是可以被证明的,但使用一个好的哈希算法这是非常不可能的。有很多关于选择哈希算法的文章可供参考,冲突率是该选择过程中的一个重要因素。
人们提倡哈希而不是加密的原因是因为哈希是一种单向操作。哈希的优点在于它可以从用户安全性的角度考虑,因为两个值可以产生相同的哈希,所以哈希不能被反转。这使得黑客无法通过攻击您的数据库来访问其他网站的登录凭据(因为用户经常在您的系统中使用与其他网站相同的密码)。

1
一个好的实现。
  private static string CreateSalt(int size)
  {
   //Generate a cryptographic random number.
   RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
   byte[] buff = new byte[size];
   rng.GetBytes(buff);

   // Return a Base64 string representation of the random number.
   return Convert.ToBase64String(buff);
  }

private static string CreatePasswordHash(string pwd, string salt)
  {
   string saltAndPwd = String.Concat(pwd, salt);
   string hashedPwd =
    FormsAuthentication.HashPasswordForStoringInConfigFile(
    saltAndPwd, "sha1");

   return hashedPwd;
  }

来源:http://davidhayden.com/blog/dave/archive/2004/02/16/157.aspx


1

哈希函数必须被开发成极不可能为两个不同的输入提供相同哈希值,即它是抗碰撞的。更多信息可在wikipedia上获得。


1

尽管碰撞机会可能很小(取决于您的哈希算法),但这并不重要,对吧?

即使用户x和用户y具有相同的密码哈希,您也永远不会比较两个用户的密码以确定它们是否基于其哈希相同!因此,虽然“技术上”是碰撞哈希,但在这种情况下它并不会发生碰撞/干扰/影响。


1

是的,这是可能的,但对于良好的哈希函数来说不太可能。

举个例子:SHA1 是 160 位,这意味着要找到相同哈希值的两个字符串,您需要哈希大约 2^80 不同的字符串。即使使用所有最好的超级计算机,从未有人找到过哈希为相同 SHA1 值的两个字符串(虽然我预测很快会发生这种情况)。


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