关于安全性:在数据库中存储密码的最佳方式

Best way to store password in database

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

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

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

另外,如果能提供一个好的理由,我愿意接受这样一种观点:这个信息不能存储在数据库中。


正确的做法是,在纯文本字段中存储密码是一个可怕的想法。然而,就位置而言,在大多数情况下(老实说,我想不出任何反例),在数据库中存储密码的表示是正确的做法。通过表示,我的意思是您希望使用salt(对于每个用户来说应该是不同的)和安全的单向算法散列密码,并存储它,从而丢弃原始密码。然后,当您想要验证密码时,可以散列该值(使用相同的散列算法和salt),并将其与数据库中的散列值进行比较。

所以,虽然你认为这是一个好问题,但这实际上是这些问题的一个副本(至少):

  • 如何最好地存储用户信息和用户登录名和密码
  • 存储数据库密码的最佳实践
  • 加盐你的密码:最佳实践?
  • 是否可以将密码以纯文本形式存储在PHP变量或PHP常量中?

为了进一步澄清盐渍位,简单地散列一个密码并存储的危险是,如果侵入者获得了你的数据库,他们仍然可以使用所谓的彩虹表能够"解密"密码(至少那些出现在彩虹表中的密码)。为了解决这一问题,开发人员在密码中添加了一个salt,当正确地完成后,彩虹攻击就变得不可行了。请注意,一个常见的误解是简单地向所有密码添加相同的唯一和长字符串;虽然这并不可怕,但最好向每个密码添加唯一的盐。了解更多信息。


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

散列它:通过强哈希函数存储经过哈希处理的用户密码(单向加密)。搜索"C加密密码"提供了大量示例。

有关哈希函数产生的内容,请参阅联机sha1 hash creator(但不要将sha1用作哈希函数,请使用更强大的函数,如sha256)。

现在,散列密码意味着您(以及数据库窃贼)不应该能够将散列恢复为原始密码。

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

当用户登录时,他们会将用户名和密码(原始文本)交给您。您只需使用相同的散列代码散列输入的密码,以获得存储的版本。

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

额外学分:

问题:如果我有你的数据库,那我就不能像开膛手约翰那样拿个饼干开始做哈希,直到我找到与你存储的哈希密码匹配的密码吗?(因为用户总是选择简短的字典单词…应该很容易)

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

所以,你应该"盐"你的密码。参见维基百科关于盐的文章

参见"如何用salt散列数据"C示例


作为一个加密的盐散列,使用安全算法,如sha-512。


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

这样,检索纯文本密码几乎是不可能的。


我完全建议您阅读彩虹表中的文章:关于安全密码方案(死链接,在Internet存档中复制)以及如何安全存储密码,您需要了解什么。

很多编码人员,包括我自己,认为他们理解安全性和哈希。可悲的是,我们大多数人只是没有。


我可能有点偏离主题,因为你提到了用户名和密码的需求,我对这个问题的理解显然不是最好的,但OpenID值得考虑吗?

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

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

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


在您的场景中,您可以查看ASP.NET成员资格,最好将用户密码存储为数据库中的哈希字符串。您可以通过将哈希输入的密码与存储在数据库中的密码进行比较来对用户进行身份验证。

所有内容都是为此目的构建的,请查看ASP.NET成员身份


如果您不需要反向散列,我将md5/sha1密码。当用户登录时,您只需加密给定的密码并将其与散列进行比较。在这种情况下,哈希冲突几乎是不可能的,除非有人获得了对数据库的访问权,并且看到了已经有冲突的哈希。