您在数据库(最好是 SQL Server 2005)中存储密码的首选方法/数据类型是什么。我在几个应用程序中执行此操作的方法是首先使用 .NET 加密库,然后将它们作为二进制文件存储在数据库中(16)。这是首选方法还是我应该使用不同的数据类型或分配比 16 更多的空间?

有帮助吗?

解决方案

我将密码的salted哈希等价物存储在数据库中,而不是密码本身,然后总是将哈希值与用户传入的哈希值进行比较。

将文字密码数据存储在任何地方都太危险了。这使得恢复成为不可能,但是当有人忘记或丢失密码时,您可以通过一些检查并创建新密码。

其他提示

首选方法:永远不要在您的数据库中存储密码。只有哈希。加盐调味。

我做了你所描述的同样的事情,除了它存储为一个字符串。 I Base64编码加密的二进制值。分配的空间量取决于加密算法/密码强度。

我认为你做得对(假设你使用的是 Salt

  1. 存储加盐密码的哈希值,例如 bcrypt(nounce+pwd)。与 SHA1 或 MD5 相比,您可能更喜欢 bcrypt,因为它可以调整为 CPU 密集型,从而使暴力攻击的时间更长。
  2. 在出现几次登录错误后向登录表单添加验证码(以避免暴力攻击)
  3. 如果您的应用程序有“忘记密码”链接,请确保它不会通过电子邮件发送新密码,而是应发送一个指向(安全)页面的链接,允许用户定义新密码(可能仅在确认后)一些个人信息,例如用户的出生日期)。另外,如果您的应用程序允许用户定义新密码,请确保要求用户确认当前密码。
  4. 显然,保护登录表单(通常使用 HTTPS)和服务器本身

通过这些措施,您的用户密码将得到很好的保护,免受以下攻击:

  1. => 离线字典攻击
  2. => 实时字典攻击
  3. => 拒绝服务攻击
  4. => 各种攻击!

由于哈希函数的结果是一系列 0 到 255(或 -128 到 127,具体取决于 8 位数据类型的符号性)范围内的字节,因此将其存储为原始二进制字段最有意义,因为它是最紧凑的表示形式,不需要额外的编码和解码步骤。

某些数据库或驱动程序对二进制数据类型没有很好的支持,或者有时开发人员对它们不够熟悉而感到不舒服。在这种情况下,可以使用 Base-64 或 Base-85 等二进制到文本编码,并将结果文本存储在字符字段中。

所需字段的大小由您使用的哈希函数决定。MD5 始终输出 16 字节,SHA-1 始终输出 20 字节。一旦选择了哈希函数,您通常会坚持使用它,因为更改需要重置所有现有密码。因此,使用可变大小的字段不会给你带来任何好处。


关于执行散列的“最佳”方法,我尝试为有关该主题的其他问题提供许多答案:

我使用用户名的sha哈希,web配置中的guid和密码,存储为varchar(40)。如果他们想要暴力/字典,他们也需要破解Web服务器以获取guid。如果用户名确实找到了密码,则会在整个数据库中创建彩虹表。如果用户想要更改用户名,我只需要同时重置密码。

System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(
    username.ToLower().Trim(),
    ConfigurationManager.AppSettings("salt"),
    password
);

密码的简单哈希,甚至(盐+密码)通常都不够。

请参阅:

http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/

http://gom-jabbar.org/articles/2008/12/03/why-you-should-use-bcrypt-to-store-your-passwords

两者都推荐使用bcrypt算法。可以在线找到大多数流行语言的免费实施。

您可以在数据库中使用多个哈希值,只需要一点额外的努力。如果您认为将来需要支持其他格式的机会最为遥远,那么这是值得的。我经常使用密码条目,如

{hashId} $ {salt} $ {哈希密码}

其中“hashId”只是我在内部使用的一些数字来识别,例如,我正在使用具有特定散列模式的SHA1; "盐QUOT;是base64编码的随机盐;和“散列密码”是base64编码的哈希。如果您需要迁移哈希,您可以使用旧密码格式拦截人员,并在下次登录时让他们更改密码。

正如其他人提到的那样,你要小心你的哈希,因为很容易做一些不太安全的事情,例如,H(盐,密码)远远弱于H(密码,盐),但同时您希望平衡投入到此中的工作量与网站内容的价值。我经常使用H(H(密码,盐),密码)。

最后,与能够使用期望文本数据的各种工具的好处相比,使用base64编码密码的成本是适中的。是的,他们应该更灵活,但是你准备告诉你的老板他不能使用他最喜欢的第三方工具,因为你想节省每个记录几个字节? : - )

编辑添加另一条评论:如果我建议故意使用算法甚至烧掉每秒密码的十分之一秒,我很幸运会被老板的办公室嘲笑。 (不是很幸运?他会在我的下一次年度评论中记下一些事情来讨论。)当你有几十个甚至几百个用户时,燃烧那个时间不是问题。如果你推动100k用户,你通常会有多个人同时登录。你需要快速而强壮的东西,而不是缓慢而强烈的东西。 “但信用卡信息呢?”最好是不诚实,因为存储的信用卡信息不应该在您的常规数据库附近,并且无论如何都会被应用程序加密,而不是单个用户。

如果您正在使用ASP.Net,则可以使用内置的成员资格API。

它支持多种类型的存储选项,包括;单向散列,双向加密,md5 + salt。 http://www.asp.net/learn/security 了解更多信息。

如果您不需要任何太过花哨的东西,这对网站来说非常棒。

如果你没有使用ASP.Net,这里有4guys和codeproject的一些文章的很好的链接

http://aspnet.4guysfromrolla.com/articles/081705-1.aspx http://aspnet.4guysfromrolla.com/articles/103002-1.aspx http://www.codeproject.com/KB/security/SimpleEncryption.aspx

由于您的问题是关于存储方法和大小,我将解决这个问题。

存储类型可以是二进制或文本表示(base64 是最常见的)。二进制较小,但我发现处理文本更容易。如果您对每个用户进行加盐(每个密码使用不同的盐),那么将盐+哈希存储为单个组合字符串会更容易。

大小取决于哈希算法。MD5 的输出始终为 16 字节,SHA1 始终为 20 字节。SHA-256 和 SHA-512 分别是 32 和 64 字节。如果您使用文本编码,则根据编码方法,您将需要稍多的存储空间。我倾向于使用 Base64,因为存储相对便宜。Base64 将需要大约 33% 更大的字段。

如果您对每个用户加盐,您还需要哈希空间。将所有内容放在一起,64 位盐 + SHA1 哈希(160 位)base64 编码需要 40 个字符,因此我将其存储为 char(40)。

最后,如果你想做得正确,你不应该使用单个哈希,而应该使用像 RBKDF2 这样的密钥派生函数。SHA1 和 MD5 哈希值的速度非常快。即使是单线程应用程序,每秒也可以散列大约 30K 到 50K 密码,在四核计算机上每秒最多可以散列 200K 密码。GPU 每秒可以散列 100 倍到 1000 倍的密码。有了这样的速度,暴力攻击就成为一种可以接受的入侵方法。RBKDF2 允许您指定迭代次数来微调哈希的“慢”程度。重点不是让系统崩溃,而是选择迭代次数,以便限制哈希吞吐量的上限(例如每秒 500 个哈希)。一种面向未来的方法是在密码字段中包含迭代次数(迭代+盐+哈希)。这将允许未来增加迭代,以跟上更强大的处理器的步伐。为了更加灵活,使用 varchar 允许将来可能更大/替代的哈希值。

.Net 实现是 RFC2892DeriveByteshttp://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top