Castle ActiveRecord / NHibernate - 密码加密或散列

Posted

技术标签:

【中文标题】Castle ActiveRecord / NHibernate - 密码加密或散列【英文标题】:Castle ActiveRecord / NHibernate - Password Encryption or Hashing 【发布时间】:2009-01-26 00:23:27 【问题描述】:

使用您不想以明文形式存储在数据库中的密码的正确方法是什么?我在 NHibernate / Castle ActiveRecord 中有哪些选择?

更新: 我对其他人如何使用 NHibernate / Castle ActiveRecord 处理这个问题很感兴趣。 如果 NHibernate 或 Castle ActiveRecord 中内置了任何东西。

【问题讨论】:

【参考方案1】:

散列密码。不要加密 - 它很复杂和/或不安全。在普通的业务线应用程序或网站中,根据其他一些可验证的标准重置密码是不可能的。我不确定你是否熟悉哈希密码的原理,所以我将从基础开始解释......

当用户最初选择他们的密码时,您对文本运行单向哈希算法。这会产生一个签名 - 如果您将相同的字符串输入哈希算法,则始终会产生一个输出。关键是您无法从哈希中取回密码(因此是单向的)。然后,您存储哈希,而不是密码。当用户回来时,他们必须再次输入密码,您使用相同的算法对其进行哈希处理并将结果值与数据库中的值进行比较 - 如果它们匹配,您知道用户再次输入了相同的字符串,但您仍然不不知道或需要知道它是什么。这比基于加密的解决方案安全得多,在这种解决方案中,如果您知道密钥,则始终可以恢复明文,根据定义,服务器必须知道密钥才能验证密码输入。

在 .NET 中散列字符串的一种简单方法是使用 System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(),尽管它的名称很长,但它是为使用 ASP.NET 表单身份验证的用户提供的一个简单函数,但在其他地方同样有用。您可以将 MD5 或 SHA1 指定为您的哈希算法(如果未来的框架版本支持,也可以指定其他哈希算法)。我推荐 SHA1,因为已知 MD5 有弱点,但 SHA1 可能也有。

但是 - 这个方案有一个缺陷。如果多个用户选择相同的密码,他们将具有相同的哈希值。如果黑客访问了您的数据,他们可以进行暴力攻击,对常见字符串进行哈希处理,并将这些字符串与您存储的数据进行比较。如果他们受到打击,他们已经使用该密码破解了所有帐户。由于用户倾向于选择蹩脚的密码并且讨厌被要求选择他们不记得的安全密码,这使得基于简单密码哈希的系统有点脆弱。

你应该做的是 salt 哈希。这只是意味着在原始数据之前或后缀 - 密码 - 使用随机字符串。这种盐需要尽可能随机,长度至少为几个字符(我建议至少为 5 个),最好是随机长度。您将盐(未混淆)存储在数据库中的列中,旁边是散列盐 + 密码组合。当用户返回时,您以相同的方式将盐添加到他们的输入中,然后像以前一样进行哈希比较。

这会降低暴力攻击的有效性,因为每个用户都应该有不同的哈希值,即使他们有相同的密码。你可以安全地将盐存储在数据库中,因为当你知道一些字符串时,从它的哈希中计算出一个字符串和你一无所知时一样困难,只要密码本身比盐长并且足够长并且足够强大,需要很长时间才能通过蛮力破解(至少 6 个字符,至少有一个大小写更改和一个数字或非字母数字,我会说)。

如果有人可以无限时间无限访问您的数据,他们最终会破解散列密码。但最终可能是几个月或几年。如果您知道自己已被入侵,您可以在问题出现之前及时更改每个人的密码。

【讨论】:

+1 感谢伟大的信息。不过,我将更新我的问题。我更多地考虑加密/哈希应该如何与 NHibernate 和 CAR 一起工作。但是其他人应该根据散列和安全性的解释对此投赞成票。 是的,点到为止 - Mausch 上面的回答告诉您 NHibernate 如何通过 UserTypes 处理透明加密。因为散列是单向的,所以我不知道在 NHibernate 和 AR 中对它的任何特定支持。即使作为 NH 大用户,我也会自己在域对象中执行此操作。【参考方案2】:

最好的方法是使用 UserType。 Here's one 实现透明密码加密。

我会将此类常见问题复制到ActiveRecord wiki。

【讨论】:

【参考方案3】:

我建议不要将 UserType 用于单向散列,除非您有一个计划来防止在后续调用 NullSafeSet() 时不断重新散列散列密码。

相反,我建议您在 Password 属性上使用支持字段,在 setter 中应用哈希方法并设置映射以使用字段访问权限。

【讨论】:

【参考方案4】:

您应该加密或散列密码。散列更安全一些(当然取决于算法)。因为无法逆转;但是,加密可以更有效,因为您可以有一个检索密码选项。使用散列,您必须生成一个新密码..

至于 nHibernate / castle 恕我直言,您应该在业务对象中处理与持久性机制分开的算法。

【讨论】:

【参考方案5】:

对不起,也许这对你来说已经无关紧要了,但我希望可以帮助别人。

使用 uNhAddins 是我发现的最简单的方法,您只需要关心 HBM 即可。

检查这个hbm example

希望有所帮助

【讨论】:

以上是关于Castle ActiveRecord / NHibernate - 密码加密或散列的主要内容,如果未能解决你的问题,请参考以下文章

Castle ActiveRecord学习

Castle ActiveRecord学习

Castle ActiveRecord + NHibernate 中的交易傻瓜

在 Castle ActiveRecord 中按 ID 选择

Castle.ActiveRecord.PropertyAttribute.NotNull ...文档错误?

使用 Castle ActiveRecord 进行聚合查询