0

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

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

4

5 回答 5

7

Hash the password. Don't encrypt - it's complex and/or unsafe. There's no conceivable circumstance in which it wouldn't be OK to reset the password based on some other verifiable criterion in an ordinary line-of-business app or Web site. I'm not sure from the question whether or not you're familiar with the principle of hashing a password, so I'll explain from the basics...

When the user selects their password initially, you run a one-way hash algorithm on the text. This produces a signature - an output that will always be produced if you input the same string into the hash algorithm. The key is that you can't get back to the password from the hash (hence one-way). You then store the hash, not the password. When the user comes back they have to type in their password again, you hash this using the same algorithm and compare the resulting value to what's in the DB - if they match, you know the user enterered the same string again, but you still don't know, or need to know, what it is. This is much more secure than solutions based on encyrption where you can always recover the plaintext if you know the key, which by definition has to be known to the server in order to validate the password input.

A simple way of hashing a string in .NET is to use System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(), which despite its lengthy name is a simple function provided for those using ASP.NET Forms Authentication, but just as useful elsewhere. You can specify MD5 or SHA1 as your hash algorithm (or indeed other hash algorithms if supported by future framework versions). I recommend SHA1 because MD5 is known to have weaknesses, but then SHA1 probably does too.

However - there's a flaw in this scheme. If multiple users choose the same password, they will have the same hash. If a hacker gets access to your data, they can run a brute-force attack hashing common strings and comparing these against your stored data. If they get a hit, they've cracked all the accounts using that password. Since users tend to pick crappy passwords and hate being made to pick secure ones they can't remember, this makes a system based on simple password hashes a little brittle.

What you should do is salt the hash. This just means prepending or suffixing the original data - the password - with a random string of characters. This salt needs to be as random as it can be and at least a few chars in length (I recommend 5 as a minimum) and preferably of random length. You store the salt (unobfuscated) in a column in the DB alongside the hashed salt + password combination. When the user returns you prepend or suffix the salt to their input in the same way, and then do the hash comparison as before.

This reduces the effectiveness of a brute force attack because every user should have a different hash even if they have the same password. You can safely store the salt in the DB because working out a string from its hash is just as hard when you know some of the string as it is when you know none of it, provided the password itself is longer than the salt and long enough and strong enough to take a long time to crack by brute force (at least 6 chars with at least one case change and a number or non-alphanumeric, I'd say).

If someone has unlimited access to your data for unlimited time, they'll eventually crack the hashed passwords. But eventually could be months or years. And provided you know you've been compromised, you can get everyone's password changed well before it becomes a problem.

于 2009-01-27T03:45:53.270 回答
2

最好的方法是使用 UserType。这是一个实现透明密码加密的方法。

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

于 2009-01-26T00:45:36.440 回答
1

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

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

于 2010-04-16T19:27:21.970 回答
0

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

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

检查这个hbm 示例

希望有所帮助

于 2010-09-16T13:49:15.903 回答
0

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

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

于 2009-01-26T00:27:17.570 回答