Preferred method for storing passwords in a database

What is your preferred method / data type for storing passwords in a database (preferably SQL Server 2005). The way I did this 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 use a different data type or allocate more space than 16?

+75
security database passwords sql-server encryption
Mar 05 '09 at 17:10
source share
10 answers

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

It is too dangerous to store literal password data anywhere. This makes recovery impossible, but when someone forgets or loses a password, you can perform some checks and create a new password.

+80
Mar 05 '09 at 17:12
source share

Preferred Method: Never store passwords in your database. Only hashes. Add salt to taste.

+46
Mar 05 '09 at 17:16
source share

I do the same thing you described, except that it is stored as a string. I Base64 encodes an encrypted binary value. The amount of space to allocate depends on the encryption algorithm / encryption strength.

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

+15
Mar 05 '09 at 17:15
source share

Since the result of the hash function is a series of bytes in the range from 0 to 255 (or from -128 to 127, depending on the subscription of your 8-bit data type), saving it as a raw binary field makes the most sense, since it is the most compact representation and does not require additional steps of encoding and decoding.

Some databases or drivers do not have much support for binary data types, or sometimes developers are just not familiar with them to feel comfortable. In this case, using binary text encoding such as Base-64 or Base-85 and storing the resulting text in a character field is acceptable.

The size of the required field is determined by the hash function used. MD5 always outputs 16 bytes, SHA-1 always outputs 20 bytes. When you select a hash function, you are usually stuck in it, since a change requires resetting all existing passwords. Thus, using a variable size field does not buy you anything.




Regarding the “best” way to perform hashing, I tried to give a lot of answers to other SO questions on this topic:

  • Password encryption
  • Password encryption
  • Password Encryption in .NET
  • Salt
  • Salt: secret or public?
  • Hash iteration
+8
Mar 05 '09 at 17:22
source share
  • save the hash with a salty password, for example, bcrypt (nounce + pwd). You may prefer bcrypt over SHA1 or MD5, because it can be tuned to the processor intensity, therefore a more intense brute force attack method.
  • add a captcha to the login form after several login errors (to avoid brute force attacks)
  • If your application has a “forgot my password” link, make sure that it does not send a new password by e-mail, but instead, it must send a link to a (secure) page so that the user can determine the new password (perhaps only after confirming some or personal information, such as the user's birthday, for example). In addition, if your application allows the user to define a new password, make sure that you require the user to confirm the current password.
  • and, obviously, provide a registration form (usually using HTTPS) and the servers themselves

With these measures, your user passwords will be well protected from:

  • => Attacks in the offline dictionary
  • => active dictionary attacks
  • => denial of service attacks
  • => all kinds of attacks!
+8
Mar 05 '09 at 17:51
source share

A simple password hash or even (salt + password) is usually not enough.

cm

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

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

+4
Mar 05 '09 at 18:05
source share

I use sha hash username, manual in web configuration and password stored as varchar (40). If they want to use brute force / vocabulary, they also have to hack a web server for guidance. The username breaks, creating a rainbow table across the entire database if they find the password. If the user wants to change his username, I just reset the password at the same time.

System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile( username.ToLower().Trim(), ConfigurationManager.AppSettings("salt"), password ); 
+4
Mar 05 '09 at 23:05
source share

You can use multiple hashes in your database, it just takes a little extra effort. It’s worth it, but if you think that you will be able to support additional formats in the future. I often use password entries such as

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

where "hashId" is just some number that I use internally to recognize this, for example, I use SHA1 with a specific hash pattern; “salt” is a basic 64-coded random salt; and "hashed password" is a base64 encoded hash. If you need to transfer hashes, you can intercept people with the old password and make changes to your password the next time you log in.

As already mentioned, you want to be careful with your hashes, since it is easy to do something that is really not secure, for example, H (salt, password) is much weaker than H (password, salt), but at the same time you want to balance the effort put into this with the meaning of the site content. I often use H (H (password, salt), password).

Finally, the cost of using base64-encoded passwords is modest compared to the benefits of using various tools that expect text data. Yes, they should be more flexible, but are you ready to tell your boss that he cannot use his favorite third-party tool, because you want to save several bytes for recording ?:-)

Edited to add another comment: if I proposed to intentionally use an algorithm that burned even the 1 / 10th second of hashing each password, I was lucky enough to just laugh out of my boss office. (Not so lucky? He planned something to discuss my next annual review.) Burning is not a problem when you have dozens or even hundreds of users. If you click 100 thousand users, you, as a rule, simultaneously include several people. You need something fast and strong, not slow and strong. "But what about credit card information?" at best insincere, because the stored credit card information should not be anywhere near your regular database, and in any case will be encrypted by the application, and not by individual users.

+3
Mar 23 '09 at 16:17
source share

If you work with ASP.Net, you can use the built-in membership API.

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

If you don’t need anything out of the ordinary, this is great for websites.

If you are not using ASP.Net, this is a good link to several articles from 4guys and 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

+2
Mar 05 '09 at 18:24
source share

Since your question is about the method and size of the repository, I will address this question.

The type of storage can be either binary or text (the most common is base64). The binary size is smaller, but I find working with text easier. If for each user you are poking (a different salt for the password), then it is easier to store the salt + hash in a single combined string.

Size depends on the hash algorithm. MD5 output is always 16 bytes, SHA1 is always 20 bytes. SHA-256 and SHA-512 are 32 and 64 bytes respectively. If you use text encoding, you will need a bit more memory depending on the encoding method. I use Base64 because storage is relatively cheap. Base64 will need about 33% more field.

If you have one for the user, you will need a place for the hash. Putting it all together, the 64-bit salt + SHA1 hash (160 bits) encoded by base64 takes 40 characters, so I save it as char (40).

Finally, if you want to do this correctly, you should not use a single hash, but a key derivation function such as RBKDF2. SHA1 and MD5 hashes are insanely fast. Even a single-threaded application can process from 30 to 50 thousand passwords per second, which amounts to 200 thousand passwords per second on a quad-core processor. GPUs can use as many passwords per second from 100x to 1000x. At speeds like brute force attack, it becomes an acceptable invasion method. RBKDF2 allows you to specify the number of iterations to fine-tune how “slow” your hashing is. The bottom line is to bring the system to its knees, but choose a few iterations so that you limit the upper limit of the hash bandwidth (say, 500 hashes per second). The future proof method will be to include the number of iterations in the password field (iterations + salt + hash). This will increase iterations in the future to keep up with more powerful processors. To be even more flexible, use varchar to use potentially large / alternative hashes in the future.

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

+2
Nov 16 '10 at 23:22
source share



All Articles