在数据库中存储密码的最佳方式 [已关闭]

Best way to store password in database [closed]

提问人:Crash893 提问时间:6/28/2009 最后编辑:JDoeCrash893 更新时间:6/25/2020 访问量:421289

问:

我正在处理一个必须具有身份验证(用户名和密码)的项目

它还连接到数据库,所以我想我会将用户名和密码存储在那里。但是,将密码仅作为数据库表中的文本字段似乎不是一个好主意。

我正在使用 C# 并连接到 2008 Express 服务器。谁能建议(用尽可能多的例子)存储此类数据的最佳方式是什么?

PS 如果可以提供充分的理由,我愿意接受此信息不存储在数据库中的想法

数据库 安全 密码

评论

1赞 Woody 8/3/2009
无论你做什么,如果你使用加密,不要像前面的海报那样将密钥存储在代码中。这只是糟糕的做法。
13赞 Colonel Panic 2/4/2013
“如何正确使用密码?”是一个至关重要的问题。这是一个棘手的问题,错误会产生严重的后果(回想一下Tesco和LinkedIn发生的事情)。我认为这个问题应该在 programmers.stackexchange.com 重新讨论
2赞 Boris Treukhov 5/16/2014
最好坚持标准 - 参见 en.wikipedia.org/wiki/PBKDF2 你只需要找到一个用你的语言实现
7赞 gioele 11/12/2014
这个问题在安全论坛中得到了广泛的回答:security.stackexchange.com/questions/211/......
6赞 Przemyslaw 7/10/2022
❗❗❗ PSA,因为这个问题得到了很多观点,同时有一些可怕的危险想法 - 永远不要使用家庭中的任何东西进行密码哈希 - 这些是所谓的“快速哈希”,而对于密码,你想看“慢哈希”,相反。 是此评论时的最爱,其他可接受的选项是 、 或 。有关哈希和存储建议,请始终咨询OWASP:cheatsheetseries.owasp.org/cheatsheets/...SHAArgon2idscryptbcryptPBKDF2

答:

1赞 waiwai933 6/28/2009 #1

如果您不需要能够反转哈希,我会MD5 / SHA1密码。当用户登录时,您只需加密给定的密码并将其与哈希值进行比较即可。在这种情况下,哈希冲突几乎是不可能的,除非有人获得对数据库的访问权限并看到他们已经发生冲突的哈希。

评论

2赞 zebrabox 6/28/2009
我不会使用 MD5 进行哈希处理 - 它基本上已经损坏了 mscs.dal.ca/~selinger/md5collision
3赞 waiwai933 6/29/2009
实际上,它并没有那么坏。他们能做的就是为两个不同的文件找到相同的哈希值。他们不能做的是反转MD5并获取有效密码。
2赞 mjuarez 2/10/2013
好吧,那不是也被打破了吗?您只需输入生成相同哈希值的另一个密码,即可进入。您不需要知道原始密码。解决此问题的方法是在哈希之前对密码加盐。
3赞 WiiMaxx 10/11/2013
@mjuarez,如果您在密码中添加了盐,则使用MD5,则冲突无关紧要,因为您不能使用其他密码
3赞 Ray Lu 6/28/2009 #2

在您的方案中,您可以查看 asp.net 成员身份,最好将用户的密码作为哈希字符串存储在数据库中。您可以通过将经过哈希处理的传入密码与数据库中存储的密码进行比较来验证用户身份。

一切都是为此目的而构建的,请查看 asp.net 会员资格

468赞 Paolo Bergantino 6/28/2009 #3

您说得对,将密码存储在纯文本字段中是一个可怕的主意。但是,就位置而言,对于您将遇到的大多数情况(老实说,我想不出任何反例),将密码的表示形式存储在数据库中是正确的做法。通过表示,我的意思是您希望使用盐(每个用户都应该不同)和安全的单向算法对密码进行哈希处理并存储,扔掉原始密码。然后,当您要验证密码时,对该值进行哈希处理(使用相同的哈希算法和盐),并将其与数据库中的哈希值进行比较。

所以,虽然你正在考虑这个问题是一件好事,这是一个很好的问题,但这实际上是这些问题的重复(至少):

为了进一步澄清加盐位,简单地散列密码并存储密码的危险在于,如果入侵者掌握了您的数据库,他们仍然可以使用所谓的彩虹表来“解密”密码(至少是那些出现在彩虹表中的密码)。为了解决这个问题,开发人员在密码中添加了,如果操作得当,彩虹攻击根本无法进行。请注意,一个常见的误解是简单地将相同的唯一长字符串添加到所有密码中;虽然这并不可怕,但最好在每个密码中添加独特的盐。阅读此内容以了解更多信息。

评论

44赞 Paolo Bergantino 6/28/2009
我的意思是将密码存储在数据库中,而不是将其存储在其他地方。断章取义使我看起来像是在支持存储普通密码,如果您阅读其余部分,我显然不支持。
16赞 Paolo Bergantino 6/28/2009
我不仅这么说,还把他引向了大量讨论盐之类的帖子......
1赞 Mitch Wheat 6/28/2009
@Paolo Bergantino:你确定你的帖子中没有错别字吗?它说:“对于您将遇到的大多数情况(老实说,我想不出任何反例),将密码存储在数据库中是正确的做法???。这似乎削弱了你的评论
3赞 Robert Rossney 6/29/2009
保罗说的话直接自相矛盾。密码的加盐哈希不是密码。在数据库中存储密码的加盐哈希值不会将密码存储在数据库中。答案的正文非常恰当,但它的第一句话极具误导性。
46赞 Paolo Bergantino 6/29/2009
@Robert:这已经危险地接近于一个琐碎的语义游戏,但我还是会修复它......
32赞 nilamo 6/28/2009 #4

作为密钥强化的加盐哈希,使用安全算法(如 sha-512)。

评论

7赞 Dynom 6/3/2014
在我看来,您应该始终使用慢速算法(例如Blowfish)来存储密码。这篇文章是一个更好的答案:security.stackexchange.com/questions/211/......。只是把它放在这里,因为这个页面仍然出现在搜索结果中。
2赞 mlissner 5/29/2015
遵循此密码存储建议将大错特错。
29赞 Mitch Wheat 6/28/2009 #5

最佳安全做法是根本不存储密码(甚至不加密),而是存储加密密码的加盐哈希(每个密码具有唯一的盐)。

这样(实际上)就不可能检索明文密码。

评论

11赞 Mike Rosenblum 6/28/2009
Wayne,通过在计算哈希值之前加盐,如果盐有足够的大小,彩虹表就会被有效地击败。
12赞 Ian Boyd 2/25/2010
@Wayne Hartman:不是这样。如果盐值已公开,则必须为该特定盐值生成新的彩虹表。彩虹表的重点是事先计算哈希值。没有人会为他的特定盐提供彩虹桌。
67赞 joej 6/28/2009 #6

背景你从不......真。。。需要知道用户的密码。您只想验证传入用户是否知道帐户的密码。

散列一下:通过强哈希函数存储经过哈希处理(单向加密)的用户密码。 搜索“c# 加密密码”会提供大量示例。

请参阅在线 SHA1 哈希创建器,了解哈希函数生成的内容(但不要使用 SHA1 作为哈希函数,请使用更强大的功能,例如 SHA256)。

现在,哈希密码意味着您(和数据库窃贼)不应该能够将该哈希反转回原始密码。

如何使用它:但是,你说,我如何使用存储在数据库中的这个混搭密码?

当用户登录时,他们会向你提供用户名和密码(原始文本) 您只需使用相同的哈希代码对键入的密码进行哈希处理即可获取存储的版本。

因此,比较两个哈希密码(用户名的数据库哈希和输入的哈希密码)。您可以通过比较他们的哈希值来判断“他们输入的内容”是否与“原始用户为其密码输入的内容”匹配。

额外积分:

问题:如果我有你的数据库,那么我就不能拿一个像开膛手约翰这样的破解者,开始进行哈希,直到我找到与你存储的哈希密码相匹配的密码吗? (因为用户无论如何都会选择简短的字典单词......应该很容易)

答:是的。。。是的,他们可以。

因此,您应该“加盐”您的密码。 请参阅维基百科上关于盐的文章

请参阅“如何使用 salt 对数据进行哈希处理”C# 示例(已存档)

评论

15赞 Paolo Bergantino 6/28/2009
不错的帖子,除了一件事:md5 和 sha1 都被破坏了。您可能应该使用更强大的算法,例如 SHA2 系列。
3赞 joej 6/29/2009
谢谢保罗,你是对的。由于 SHA2 的使用与使用 MD5 和 SHA1 一样简单,请使用更强的哈希算法。
5赞 Ian Boyd 2/25/2010
SHA-1 尚未被破坏。但对布鲁斯·施奈尔(Bruce Schneier)来说:走路,不要跑,到SHA-2。
5赞 trusktr 11/18/2013
“所以,你应该'加盐'你的密码”......但是盐通常与密码一起存储在数据库中,那么这有什么帮助呢?攻击者只需在他正在测试的字典攻击短语中添加盐即可。除了不会泄露重复密码之外,这如何更安全?
5赞 Francisco Zarabozo 9/21/2015
@joej “你从来不......真。。。需要知道用户的密码“——这是一个非常短视的假设。在许多类型的应用程序中,以可以检索的方式存储密码是真正必要的。例如,应用程序需要频繁使用用户提供和更新的存储凭据登录到另一个系统。
6赞 Crippledsmurf 6/28/2009 #7

我可能有点跑题了,因为你确实提到了需要用户名和密码,我对这个问题的理解公认不是最好的,但 OpenID 值得考虑吗?

如果您使用 OpenID,那么如果我正确理解该技术,并且用户可以使用他们已经拥有的凭据,那么您最终根本不会存储任何凭据,从而避免了创建特定于您的应用程序的新标识的需要。

但是,如果所讨论的应用程序纯粹供内部使用,则它可能不适合

RPX 提供了一种将 OpenID 支持集成到应用程序中的简单方法。

评论

0赞 Crash893 6/29/2009
我同意 openID 震撼了人们的对峙,但对于这个应用程序,它是一家公司的内部数据库,我怀疑他们是否希望任何老人进来登录。此外,此应用程序不需要 Web 访问即可正常工作,因此我不想要求它。
12赞 zebrabox 6/28/2009 #8

我强烈建议您阅读文章 Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes [dead link, copy at the Internet Archive] 和 How To Secure Store A Password.

很多程序员,包括我自己,都认为他们了解安全和哈希。可悲的是,我们大多数人都没有。

评论

1赞 zebrabox 5/26/2011
@Johan 看起来链接现在坏了,真是太可惜了。这是另一种 codahale.com/how-to-safely-store-a-password