我正在开发一个必须具有身份验证(用户名和密码)的项目
它还连接到数据库,所以我想我会在那里存储用户名和密码。但是,将密码仅仅放在数据库中的表中的文本字段似乎不是一个好主意。
我正在使用C#并连接到2008 Express服务器。任何人都可以建议(尽可能多的例子)存储此类数据的最佳方法是什么?
P.S我愿意这样的想法,如果可以提供一个很好的理由,这些信息不会存储在数据库中
答案 0 :(得分:379)
将密码存储在纯文本字段中是正确的,这是一个可怕的想法。但是,就位置而言,对于您将要遇到的大多数情况(我真的想不出任何反例)存储表示数据库中的密码是正确的做法。通过表示我的意思是你想使用salt(对每个用户应该是不同的)和安全的单向算法来存储密码,并存储 ,丢弃原始密码。然后,当您想验证密码时,您可以散列该值(使用相同的散列算法和salt)并将其与数据库中的散列值进行比较。
所以,虽然你正在思考这个问题并且这是一个好问题,但这实际上是这些问题的重复(至少):
为了进一步澄清盐渍位,只需对密码进行哈希处理以及存储密码的危险就是如果侵入者掌握了数据库,他们仍然可以使用所谓的rainbow tables能够“解密”密码(至少那些出现在彩虹表中的密码)。为了解决这个问题,开发人员在密码中添加salt密码,这些密码在正确完成后会使彩虹攻击变得不可行。请注意,一个常见的误解是简单地为所有密码添加相同的唯一和长字符串;虽然这不是可怕的,但最好为每个密码添加唯一的盐。 Read this for more.
答案 1 :(得分:49)
<强>背景强> 你永远......真的......需要知道用户的密码。您只想验证传入的用户是否知道帐户的密码。
哈希: 通过强哈希函数存储用户密码哈希(单向加密)。 搜索“c#encrypt passwords”可以提供大量示例。
请参阅online SHA1 hash creator以了解哈希函数产生的内容(但不要使用SHA1作为哈希函数,使用更强大的东西,如SHA256)。
现在,散列密码意味着您(和数据库窃贼)不应该将该散列反转回原始密码。
如何使用 但是,你说,我如何使用存储在数据库中的这个混合密码?
当用户登录时,他们会向您提供用户名和密码(原始文本) 您只需使用相同的哈希码来哈希该输入的密码即可获得存储的版本。
因此,比较两个散列密码(用户名的数据库哈希和键入的密码和哈希密码)。您可以通过比较它们的哈希值来判断“他们输入的内容”是否与“原始用户为其密码输入的内容”相匹配。
额外信用:
问题:如果我有你的数据库,那么我不能像开膛手约翰那样拿一个黑客并开始哈希,直到找到你存储的哈希密码匹配? (因为用户选择简短的字典单词......应该很容易)
答案:是的......是的,他们可以。
所以,你应该“加密”你的密码。 请参阅Wikipedia article on salt
答案 2 :(得分:30)
使用安全算法(如sha-512)作为密钥加强的盐渍哈希。
答案 3 :(得分:26)
最好的安全措施不是存储密码(甚至不加密),而是存储加密密码的盐渍哈希(每个密码使用一个唯一的盐)。
这样(实际上)无法检索明文密码。
答案 4 :(得分:10)
我完全建议您阅读文章Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes [死链接,copy at the Internet Archive]和How To Safely Store A Password。
包括我自己在内的许多程序员都认为他们理解安全性和散列。可悲的是,我们大多数人都没有。
答案 5 :(得分:6)
我可能稍微偏离主题,因为你提到了用户名和密码的需要,而我对这个问题的理解并不是最好的,但OpenID是值得考虑的事情吗?
如果您使用OpenID,那么如果我正确理解了技术并且用户可以使用他们已有的凭据,那么您根本不会最终存储任何凭据,从而无需创建特定于您的应用程序的新身份。
如果有问题的申请仅供内部使用,可能不适合
RPX提供了一种将OpenID支持集成到应用程序中的简便方法。
答案 6 :(得分:3)
在您的场景中,您可以查看asp.net成员资格,最好将用户密码作为散列字符串存储在数据库中。您可以通过将散列的传入密码与存储在数据库中的密码进行比较来验证用户身份。
所有内容都是为此目的而构建的,请查看asp.net membership
答案 7 :(得分:2)
如果您不需要能够反转哈希,我会将MD5 / SHA1作为密码。当用户登录时,您只需加密给定的密码并将其与散列进行比较即可。在这种情况下,哈希冲突几乎是不可能的,除非有人获得对数据库的访问权并看到他们已经发生冲突的哈希值。