在数据库中存储密码的首选方法。

时间:2022-04-29 17:01:22

What is your preferred method/datatype for storing passwords in a database (preferably SQL Server 2005). The way I have been doing it in several of our applications is to first use the .NET encryption libraries and then store them in the database as binary(16). Is this the preferred method or should I be using a different datatype or allocating more space than 16?

在数据库中存储密码的首选方法/数据类型是什么(最好是SQL Server 2005)。我在我们的几个应用程序中所做的就是首先使用。net加密库,然后将它们作为二进制(16)存储在数据库中。这是首选的方法,还是应该使用不同的数据类型,或者分配超过16的空间?

10 个解决方案

#1


80  

I store the salted hash equivalent of the password in the database and never the password itself, then always compare the hash to the generated one of what the user passed in.

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

It's too dangerous to ever store the literal password data anywhere. This makes recovery impossible, but when someone forgets or loses a password you can run through some checks and create a new password.

在任何地方存储文字密码都太危险了。这使得恢复变得不可能,但是当有人忘记或丢失密码时,您可以运行一些检查并创建一个新的密码。

#2


46  

THE preferred method: never store passwords in your DB. Only hashes thereof. Add salt to taste.

首选方法:永远不要将密码存储在数据库中。只有散列。加盐调味。

#3


15  

I do the same thing you've described, except it is stored as a String. I Base64 encode the encrypted binary value. The amount of space to allocate depends on the encryption algorithm/cipher strength.

我做的和你描述的一样,只是它被存储为一个字符串。我对加密的二进制值进行了Base64编码。分配的空间大小取决于加密算法/密码强度。

I think you are doing it right (given that you use a Salt).

我认为你做得对(考虑到你用的是盐)。

#4


8  

Since the result of a hash function is a series of byte in the range 0 to 255 (or -128 to 127, depending the signed-ness of your 8-bit data type), storing it as a raw binary field makes the most sense, as it is the most compact representation and requires no additional encoding and decoding steps.

因为一个哈希函数的结果是一系列的字节范围在0到255(或-128年到127年,signed-ness 8位数据类型),它作为原始二进制存储领域最具意义,因为它是最紧凑的表示,不需要额外的编码和解码步骤。

Some databases or drivers don't have great support for binary data types, or sometimes developers just aren't familiar enough with them to feel comfortable. In that case, using a binary-to-text encoding like Base-64 or Base-85, and storing the resulting text in a character field is acceptable.

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

The size of the field necessary is determined by the hash function that you use. MD5 always outputs 16 bytes, SHA-1 always outputs 20 bytes. Once you select a hash function, you are usually stuck with it, as changing requires a reset of all existing passwords. So, using a variable-size field doesn't buy you anything.

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


Regarding the "best" way to perform the hashing, I've tried to provide many answers to other SO questions on that topic:

关于执行散列的“最佳”方法,我尝试提供了很多关于这个主题的问题的答案:

#5


8  

  1. store the hash of the salted-password, such as bcrypt(nounce+pwd). You may prefer bcrypt over SHA1 or MD5 because it can be tuned to be CPU-intensive, therefore making a brute force attack way longer.
  2. 存储盐密码的散列,例如bcrypt(nounce+ pounce)。与SHA1或MD5相比,您可能更喜欢bcrypt,因为它可以调优为cpu密集型,因此可以延长蛮力攻击的时间。
  3. add a captcha to the login form after a few login errors (to avoid brute-force attacks)
  4. 在一些登录错误之后,在登录表单中添加一个验证码(以避免暴力攻击)
  5. if your application has a "forgot my password" link, make sure it does not send the new password by email, but instead it should send a link to a (secured) page allowing the user to define a new password (possibly only after confirmation of some personal information, such as the user's birth date, for example). Also, if your application allows the user to define a new password, make sure you require the user to confirm the current password.
  6. 如果您的应用程序有一个“忘记密码”链接,确保它不通过电子邮件发送新密码,而是应该发送一个链接到一个页面(担保)允许用户定义一个新密码(可能只有在确认一些个人信息,如用户的出生日期,例如)。此外,如果应用程序允许用户定义新密码,请确保要求用户确认当前密码。
  7. and obviously, secure the login form (typically with HTTPS) and the servers themselves
  8. 显然,要保护登录表单(通常是HTTPS)和服务器本身

With these measures, your user's passwords will be fairly well protected against:

有了这些措施,你的用户的密码就会得到很好的保护:

  1. => offline dictionary attacks
  2. = >离线字典攻击
  3. => live dictionary attacks
  4. = >生活字典攻击
  5. => denial of service attacks
  6. =>拒绝服务攻击。
  7. => all sorts of attacks!
  8. 各种各样的攻击!

#6


4  

I use the sha hash of the username, a guid in the web config, and the password, stored as a varchar(40). If they want to brute force / dictionary they'll need to hack the web server for the guid as well. The username breaks creating a rainbow table across the whole database if they do find the password. If a user wants to change their username, I just reset the password at the same time.

我使用用户名的sha哈希,web配置中的guid,以及作为varchar(40)存储的密码。如果他们想要使用蛮力/字典,他们还需要为guid入侵web服务器。如果用户名找到密码,就会在整个数据库中创建彩虹表。如果用户想更改他们的用户名,我只需同时重置密码。

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

#7


3  

A simple hash of the password, or even (salt + password) is not generally adequate.

一个简单的密码哈希(salt + password)通常是不够的。

see:

看到的:

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

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

and

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

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

Both recommend the bcrypt algorithms. Free implementations can be found online for most popular languages.

两者都推荐bcrypt算法。对于大多数流行的语言,可以在网上找到免费的实现。

#8


3  

You can use multiple hashes in your database, it just requires a little bit of extra effort. It's well worth it though if you think there's the remotest chance you'll need to support additional formats in the future. I'll often use password entries like

您可以在您的数据库中使用多个散列,这只需要一点额外的努力。不过,如果您认为将来需要支持其他格式的可能性很小,那么这是非常值得的。我经常使用密码条目,比如

{hashId}${salt}${hashed password}

{哈希德} $ {盐} $ { }散列密码

where "hashId" is just some number I use internally to recognize that, e.g., I'm using SHA1 with a specific hash pattern; "salt" is a base64-encoded random salt; and "hashed password" is a base64-encoded hash. If you need to migrate hashes you can intercept people with an old password format and make them change their password the next time they log in.

这里的“hashId”只是我内部用来识别它的一些数字,例如,我使用SHA1进行特定的散列模式;“盐”是一种base64编码的随机盐;“散列密码”是一个base64编码的散列。如果您需要迁移散列,您可以使用旧密码格式拦截用户,并在下次登录时更改其密码。

As others have mentioned you want to be careful with your hashes since it's easy to do something that's not really secure, e.g., H(salt,password) is far weaker than H(password,salt), but at the same time you want to balance the effort put into this with the value of the site content. I'll often use H(H(password,salt),password).

正如其他人提到的那样,您需要小心处理散列,因为做一些不太安全的事情很容易,例如,H(salt,password)要比H(password,salt)弱得多,但同时您需要平衡投入的精力与站点内容的价值。我会经常使用H(H(密码、盐),密码)。

Finally, the cost of using base64-encoded passwords is modest when compared to the benefits of being able to use various tools that expect text data. Yeah, they should be more flexible, but are you ready to tell your boss that he can't use his favorite third party tool because you want to save a few bytes per record? :-)

最后,使用base64编码的密码的成本与能够使用各种预期文本数据的工具相比是不高的。是的,他们应该更灵活,但是你准备好告诉你的老板他不能使用他最喜欢的第三方工具了吗?:-)

Edited to add one other comment: if I suggested deliberately using an algorithm that burned even a 1/10th of a second hashing each password I would be lucky to just be laughed out of my boss's office. (Not so lucky? He would jot something down to discuss at my next annual review.) Burning that time isn't a problem when you have dozens, or even hundreds, of users. If you're pushing 100k users you'll usually have multiple people logging in at the same time. You need something fast and strong, not slow and strong. The "but what about the credit card information?" is disingenuous at best since stored credit card information shouldn't be anywhere near your regular database, and would be encrypted by the application anyway, not individual users.

如果我有意使用一种算法,它甚至会把每一个密码都烧成1/10秒,那么我就很幸运了,只是被老板的办公室笑了出来。(没那么幸运?他会记下一些东西,在我下一次年度审查时讨论。当你有几十个甚至上百个用户时,浪费时间并不是问题。如果你推了10万用户,你通常会有很多人同时登录。你需要的是快速而有力的东西,而不是缓慢而强大的东西。“但是信用卡信息呢?”是不诚实的,因为存储信用卡信息不应该在你的常规数据库附近,而且会被应用程序加密,而不是个人用户。

#9


2  

If you are working with ASP.Net you can use the built in membership API.

如果你在使用ASP。Net可以使用内置的会员制API。

It supports many types of storage options, inlcuding; one way hash, two way encryption, md5 + salt. http://www.asp.net/learn/security for more info.

它支持多种类型的存储选项,inlcuding;单向哈希,双向加密,md5 + salt。http://www.asp.net/learn/security以获得更多信息。

If you dont need anything too fancy, this is great for websites.

如果你不需要太花哨的东西,这对网站来说是很好的选择。

If you are not using ASP.Net here is a good link to a few articles from 4guys and codeproject

如果您不使用ASP。这里有一个很好的链接到来自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

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

#10


2  

Since your question is about storage method & size I will address that.

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

Storage type can be either binary or text representation (base64 is the most common). Binary is smaller but I find working with text easier. If you are doing per user salting (different salt per password) then it is easier to store salt+hash as a single combined string.

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

The size is hash algorithm dependent. The output of MD5 is always 16 bytes, SHA1 is always 20 bytes. SHA-256 & SHA-512 are 32 & 64 bytes respectively. If you are using text encoding you will need slightly more storage depending on the encoding method. I tend to use Base64 because storage is relatively cheap. Base64 is going to require roughly 33% larger field.

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

If you have per user salting you will need space for the hash also. Putting it all together 64bit salt + SHA1 hash (160 bit) base64 encoded takes 40 characters so I store it as char(40).

如果您有每个用户的salting,那么您还需要为散列空间。将64位salt + SHA1散列(160位)base64编码需要40个字符,所以我将它存储为char(40)。

Lastly if you want to do it right you shouldn't be using a single hash but a key derivation function like RBKDF2. SHA1 and MD5 hashes are insanely fast. Even a single threaded application can hash about 30K to 50K passwords per second thats up to 200K passwords per second on quad core machine. GPUs can hash 100x to 1000x as many passwords per second.With speeds like that brute force attacking becomes an acceptable intrusion method. RBKDF2 allows you to specify the number of iterations to fine tune how "slow" your hashing is. The point isn' to bring the system to its knees but to pick a number of iterations so that you cap upper limit on hash throughput (say 500 hashes per second). A future proof method would be to include the number of iterations in the password field (iterations + salt + hash). This would allow increasing iterations in the future to keep pace with more powerful processors. To be even more flexible use varchar to allow potentially larger/alternative hashes in the future.

最后,如果你想做对的话,你不应该只使用一个散列,而应该使用一个关键的派生函数,比如RBKDF2。SHA1和MD5散列速度快得惊人。即使是一个单线程应用程序,每秒也可以哈希大约30K到50K个密码,这相当于四核计算机每秒最多可以哈希200K个密码。gpu可以散列100x到1000x,每秒钟最多可以生成100个密码。使用蛮力攻击这样的速度成为可以接受的入侵方法。RBKDF2允许您指定迭代的数量,以调整哈希的“慢”程度。关键是要“使系统处于瘫痪状态,但要选择一些迭代,这样才能限制哈希吞吐量的上限(比如每秒500个哈希)。”未来的证明方法是在密码字段中包含迭代次数(迭代+盐+哈希)。这将允许在未来增加迭代,以跟上更强大处理器的步伐。为了更加灵活,使用varchar可以在将来允许更大的/可选的散列。

The .Net implementation is RFC2892DeriveBytes http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

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

#1


80  

I store the salted hash equivalent of the password in the database and never the password itself, then always compare the hash to the generated one of what the user passed in.

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

It's too dangerous to ever store the literal password data anywhere. This makes recovery impossible, but when someone forgets or loses a password you can run through some checks and create a new password.

在任何地方存储文字密码都太危险了。这使得恢复变得不可能,但是当有人忘记或丢失密码时,您可以运行一些检查并创建一个新的密码。

#2


46  

THE preferred method: never store passwords in your DB. Only hashes thereof. Add salt to taste.

首选方法:永远不要将密码存储在数据库中。只有散列。加盐调味。

#3


15  

I do the same thing you've described, except it is stored as a String. I Base64 encode the encrypted binary value. The amount of space to allocate depends on the encryption algorithm/cipher strength.

我做的和你描述的一样,只是它被存储为一个字符串。我对加密的二进制值进行了Base64编码。分配的空间大小取决于加密算法/密码强度。

I think you are doing it right (given that you use a Salt).

我认为你做得对(考虑到你用的是盐)。

#4


8  

Since the result of a hash function is a series of byte in the range 0 to 255 (or -128 to 127, depending the signed-ness of your 8-bit data type), storing it as a raw binary field makes the most sense, as it is the most compact representation and requires no additional encoding and decoding steps.

因为一个哈希函数的结果是一系列的字节范围在0到255(或-128年到127年,signed-ness 8位数据类型),它作为原始二进制存储领域最具意义,因为它是最紧凑的表示,不需要额外的编码和解码步骤。

Some databases or drivers don't have great support for binary data types, or sometimes developers just aren't familiar enough with them to feel comfortable. In that case, using a binary-to-text encoding like Base-64 or Base-85, and storing the resulting text in a character field is acceptable.

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

The size of the field necessary is determined by the hash function that you use. MD5 always outputs 16 bytes, SHA-1 always outputs 20 bytes. Once you select a hash function, you are usually stuck with it, as changing requires a reset of all existing passwords. So, using a variable-size field doesn't buy you anything.

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


Regarding the "best" way to perform the hashing, I've tried to provide many answers to other SO questions on that topic:

关于执行散列的“最佳”方法,我尝试提供了很多关于这个主题的问题的答案:

#5


8  

  1. store the hash of the salted-password, such as bcrypt(nounce+pwd). You may prefer bcrypt over SHA1 or MD5 because it can be tuned to be CPU-intensive, therefore making a brute force attack way longer.
  2. 存储盐密码的散列,例如bcrypt(nounce+ pounce)。与SHA1或MD5相比,您可能更喜欢bcrypt,因为它可以调优为cpu密集型,因此可以延长蛮力攻击的时间。
  3. add a captcha to the login form after a few login errors (to avoid brute-force attacks)
  4. 在一些登录错误之后,在登录表单中添加一个验证码(以避免暴力攻击)
  5. if your application has a "forgot my password" link, make sure it does not send the new password by email, but instead it should send a link to a (secured) page allowing the user to define a new password (possibly only after confirmation of some personal information, such as the user's birth date, for example). Also, if your application allows the user to define a new password, make sure you require the user to confirm the current password.
  6. 如果您的应用程序有一个“忘记密码”链接,确保它不通过电子邮件发送新密码,而是应该发送一个链接到一个页面(担保)允许用户定义一个新密码(可能只有在确认一些个人信息,如用户的出生日期,例如)。此外,如果应用程序允许用户定义新密码,请确保要求用户确认当前密码。
  7. and obviously, secure the login form (typically with HTTPS) and the servers themselves
  8. 显然,要保护登录表单(通常是HTTPS)和服务器本身

With these measures, your user's passwords will be fairly well protected against:

有了这些措施,你的用户的密码就会得到很好的保护:

  1. => offline dictionary attacks
  2. = >离线字典攻击
  3. => live dictionary attacks
  4. = >生活字典攻击
  5. => denial of service attacks
  6. =>拒绝服务攻击。
  7. => all sorts of attacks!
  8. 各种各样的攻击!

#6


4  

I use the sha hash of the username, a guid in the web config, and the password, stored as a varchar(40). If they want to brute force / dictionary they'll need to hack the web server for the guid as well. The username breaks creating a rainbow table across the whole database if they do find the password. If a user wants to change their username, I just reset the password at the same time.

我使用用户名的sha哈希,web配置中的guid,以及作为varchar(40)存储的密码。如果他们想要使用蛮力/字典,他们还需要为guid入侵web服务器。如果用户名找到密码,就会在整个数据库中创建彩虹表。如果用户想更改他们的用户名,我只需同时重置密码。

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

#7


3  

A simple hash of the password, or even (salt + password) is not generally adequate.

一个简单的密码哈希(salt + password)通常是不够的。

see:

看到的:

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

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

and

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

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

Both recommend the bcrypt algorithms. Free implementations can be found online for most popular languages.

两者都推荐bcrypt算法。对于大多数流行的语言,可以在网上找到免费的实现。

#8


3  

You can use multiple hashes in your database, it just requires a little bit of extra effort. It's well worth it though if you think there's the remotest chance you'll need to support additional formats in the future. I'll often use password entries like

您可以在您的数据库中使用多个散列,这只需要一点额外的努力。不过,如果您认为将来需要支持其他格式的可能性很小,那么这是非常值得的。我经常使用密码条目,比如

{hashId}${salt}${hashed password}

{哈希德} $ {盐} $ { }散列密码

where "hashId" is just some number I use internally to recognize that, e.g., I'm using SHA1 with a specific hash pattern; "salt" is a base64-encoded random salt; and "hashed password" is a base64-encoded hash. If you need to migrate hashes you can intercept people with an old password format and make them change their password the next time they log in.

这里的“hashId”只是我内部用来识别它的一些数字,例如,我使用SHA1进行特定的散列模式;“盐”是一种base64编码的随机盐;“散列密码”是一个base64编码的散列。如果您需要迁移散列,您可以使用旧密码格式拦截用户,并在下次登录时更改其密码。

As others have mentioned you want to be careful with your hashes since it's easy to do something that's not really secure, e.g., H(salt,password) is far weaker than H(password,salt), but at the same time you want to balance the effort put into this with the value of the site content. I'll often use H(H(password,salt),password).

正如其他人提到的那样,您需要小心处理散列,因为做一些不太安全的事情很容易,例如,H(salt,password)要比H(password,salt)弱得多,但同时您需要平衡投入的精力与站点内容的价值。我会经常使用H(H(密码、盐),密码)。

Finally, the cost of using base64-encoded passwords is modest when compared to the benefits of being able to use various tools that expect text data. Yeah, they should be more flexible, but are you ready to tell your boss that he can't use his favorite third party tool because you want to save a few bytes per record? :-)

最后,使用base64编码的密码的成本与能够使用各种预期文本数据的工具相比是不高的。是的,他们应该更灵活,但是你准备好告诉你的老板他不能使用他最喜欢的第三方工具了吗?:-)

Edited to add one other comment: if I suggested deliberately using an algorithm that burned even a 1/10th of a second hashing each password I would be lucky to just be laughed out of my boss's office. (Not so lucky? He would jot something down to discuss at my next annual review.) Burning that time isn't a problem when you have dozens, or even hundreds, of users. If you're pushing 100k users you'll usually have multiple people logging in at the same time. You need something fast and strong, not slow and strong. The "but what about the credit card information?" is disingenuous at best since stored credit card information shouldn't be anywhere near your regular database, and would be encrypted by the application anyway, not individual users.

如果我有意使用一种算法,它甚至会把每一个密码都烧成1/10秒,那么我就很幸运了,只是被老板的办公室笑了出来。(没那么幸运?他会记下一些东西,在我下一次年度审查时讨论。当你有几十个甚至上百个用户时,浪费时间并不是问题。如果你推了10万用户,你通常会有很多人同时登录。你需要的是快速而有力的东西,而不是缓慢而强大的东西。“但是信用卡信息呢?”是不诚实的,因为存储信用卡信息不应该在你的常规数据库附近,而且会被应用程序加密,而不是个人用户。

#9


2  

If you are working with ASP.Net you can use the built in membership API.

如果你在使用ASP。Net可以使用内置的会员制API。

It supports many types of storage options, inlcuding; one way hash, two way encryption, md5 + salt. http://www.asp.net/learn/security for more info.

它支持多种类型的存储选项,inlcuding;单向哈希,双向加密,md5 + salt。http://www.asp.net/learn/security以获得更多信息。

If you dont need anything too fancy, this is great for websites.

如果你不需要太花哨的东西,这对网站来说是很好的选择。

If you are not using ASP.Net here is a good link to a few articles from 4guys and codeproject

如果您不使用ASP。这里有一个很好的链接到来自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

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

#10


2  

Since your question is about storage method & size I will address that.

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

Storage type can be either binary or text representation (base64 is the most common). Binary is smaller but I find working with text easier. If you are doing per user salting (different salt per password) then it is easier to store salt+hash as a single combined string.

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

The size is hash algorithm dependent. The output of MD5 is always 16 bytes, SHA1 is always 20 bytes. SHA-256 & SHA-512 are 32 & 64 bytes respectively. If you are using text encoding you will need slightly more storage depending on the encoding method. I tend to use Base64 because storage is relatively cheap. Base64 is going to require roughly 33% larger field.

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

If you have per user salting you will need space for the hash also. Putting it all together 64bit salt + SHA1 hash (160 bit) base64 encoded takes 40 characters so I store it as char(40).

如果您有每个用户的salting,那么您还需要为散列空间。将64位salt + SHA1散列(160位)base64编码需要40个字符,所以我将它存储为char(40)。

Lastly if you want to do it right you shouldn't be using a single hash but a key derivation function like RBKDF2. SHA1 and MD5 hashes are insanely fast. Even a single threaded application can hash about 30K to 50K passwords per second thats up to 200K passwords per second on quad core machine. GPUs can hash 100x to 1000x as many passwords per second.With speeds like that brute force attacking becomes an acceptable intrusion method. RBKDF2 allows you to specify the number of iterations to fine tune how "slow" your hashing is. The point isn' to bring the system to its knees but to pick a number of iterations so that you cap upper limit on hash throughput (say 500 hashes per second). A future proof method would be to include the number of iterations in the password field (iterations + salt + hash). This would allow increasing iterations in the future to keep pace with more powerful processors. To be even more flexible use varchar to allow potentially larger/alternative hashes in the future.

最后,如果你想做对的话,你不应该只使用一个散列,而应该使用一个关键的派生函数,比如RBKDF2。SHA1和MD5散列速度快得惊人。即使是一个单线程应用程序,每秒也可以哈希大约30K到50K个密码,这相当于四核计算机每秒最多可以哈希200K个密码。gpu可以散列100x到1000x,每秒钟最多可以生成100个密码。使用蛮力攻击这样的速度成为可以接受的入侵方法。RBKDF2允许您指定迭代的数量,以调整哈希的“慢”程度。关键是要“使系统处于瘫痪状态,但要选择一些迭代,这样才能限制哈希吞吐量的上限(比如每秒500个哈希)。”未来的证明方法是在密码字段中包含迭代次数(迭代+盐+哈希)。这将允许在未来增加迭代,以跟上更强大处理器的步伐。为了更加灵活,使用varchar可以在将来允许更大的/可选的散列。

The .Net implementation is RFC2892DeriveBytes http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

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