使用您不希望以明文形式存储在数据库中的密码的正确方法是什么?我在NHibernate/Castle ActiveRecord中有哪些选择?
更新: 我对其他人如何处理NHibernate/Castle ActiveRecord感兴趣.如果NHibernate或Castle ActiveRecord中有任何内置功能.
哈希密码.不要加密 - 它很复杂和/或不安全.在普通的业务线应用程序或网站中,根据其他一些可验证的标准重置密码是不可能的.我不确定你是否熟悉哈希密码的原理,所以我将从基础知识中解释......
当用户最初选择其密码时,您会在文本上运行单向散列算法.这会产生一个签名 - 如果您在哈希算法中输入相同的字符串,将始终生成一个输出.关键是你无法从哈希中回到密码(因此是单向的).然后存储哈希值,而不是密码.当用户回来时,他们必须再次键入密码,使用相同的算法对其进行散列,并将结果值与数据库中的值进行比较 - 如果匹配,您知道用户再次输入相同的字符串,但您仍然不知道不知道,或者需要知道它是什么.这比基于encyrption的解决方案更安全,如果您知道密钥,则可以始终恢复明文,根据定义,必须知道服务器以验证密码输入.
在.NET中散列字符串的简单方法是使用System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile()
,尽管名称冗长,但是为使用ASP.NET Forms Authentication的人提供了一个简单的函数,但在其他地方也同样有用.您可以将MD5或SHA1指定为哈希算法(如果未来的框架版本支持,则可以指定其他哈希算法).我推荐使用SHA1,因为已知MD5存在缺陷,但SHA1可能也有.
但是 - 这个方案存在缺陷.如果多个用户选择相同的密码,则它们将具有相同的哈希值.如果黑客可以访问您的数据,他们可以运行强制攻击来散列常见字符串并将这些字符串与您存储的数据进行比较.如果他们受到了打击,他们就会使用该密码破解所有帐户.由于用户倾向于选择糟糕的密码并且不喜欢选择他们记不起的安全密码,这使得基于简单密码哈希的系统变得有点脆弱.
你应该做的是盐的哈希值.这只是意味着在原始数据(密码)之前加上或后缀一个随机的字符串.这种盐需要尽可能随机,并且长度至少为几个(我建议最少5个),最好是随机长度.您将盐(未经模糊处理)存储在数据库的一列中,并与散列盐+密码组合一起存储.当用户返回时,以相同的方式将salt添加到其输入的前缀或后缀,然后像以前一样进行哈希比较.
这降低了暴力攻击的有效性,因为即使用户具有相同的密码,每个用户也应该具有不同的哈希值.您可以安全地将盐存储在数据库中,因为当您知道某些字符串时,如果您知道其中没有字符串,那么从其哈希处理字符串就一样困难,前提是密码本身比盐长且足够长并且强大到足以花费很长时间来蛮力破解(至少有6个字符,至少有一个案例更改和一个数字或非字母数字,我会说).
如果某人无限制地无限制地访问您的数据,他们最终将破解哈希密码.但最终可能是几个月或几年.如果您知道自己已被入侵,那么在问题成为问题之前,您可以更好地更改每个人的密码.