Best way to store password in database [closed]
Asked Answered
A

8

537

I am working on a project that has to have authentication (username and password)

It also connects to a database, so I figured I would store the username and password there. However, it seems like not such a good idea to have passwords as just a text field in a table sitting on the database.

I'm using C# and connecting to a 2008 express server. Can anyone suggest (with as many examples as possible) what the best way to store this type of data would be?

P.S I am open to the idea that this info not be stored in the database if a good reason can be provided

Arbour answered 28/6, 2009 at 1:50 Comment(5)
Whatever you do, if you go with encryption, don't store the key in the code as a previous poster mentioned. That's just poor practice.Frigg
'How to do passwords right?' is a vital question. It's a tough problem and mistakes have grave consequences (recall what happened to Tesco and LinkedIn). I think this question should be re-opened at programmers.stackexchange.comRhettrhetta
It's better to stick to standards - see en.wikipedia.org/wiki/PBKDF2 You only have to find an implementation in your languageMacklin
This question is extensively answered in the security forum: security.stackexchange.com/questions/211/…Shoot
❗❗❗ PSA because this question gets many views while having some frighteningly dangerous ideas — never ever use anything from the SHA family for password hashing — those are the so-called "fast hashes", whereas for passwords you want to look at "slow hashes", instead. Argon2id is the favorite at the time of this comment, and other acceptable options are scrypt, bcrypt, or PBKDF2. For both hashing and storage advice, please always consult OWASP: cheatsheetseries.owasp.org/cheatsheets/…Zenaidazenana
K
470

You are correct that storing the password in a plain-text field is a horrible idea. However, as far as location goes, for most of the cases you're going to encounter (and I honestly can't think of any counter-examples) storing the representation of a password in the database is the proper thing to do. By representation I mean that you want to hash the password using a salt (which should be different for every user) and a secure 1-way algorithm and store that, throwing away the original password. Then, when you want to verify a password, you hash the value (using the same hashing algorithm and salt) and compare it to the hashed value in the database.

So, while it is a good thing you are thinking about this and it is a good question, this is actually a duplicate of these questions (at least):

To clarify a bit further on the salting bit, the danger with simply hashing a password and storing that is that if a trespasser gets a hold of your database, they can still use what are known as rainbow tables to be able to "decrypt" the password (at least those that show up in the rainbow table). To get around this, developers add a salt to passwords which, when properly done, makes rainbow attacks simply infeasible to do. Do note that a common misconception is to simply add the same unique and long string to all passwords; while this is not horrible, it is best to add unique salts to every password. Read this for more.

Kilocalorie answered 28/6, 2009 at 1:56 Comment(8)
@Paolo Bergantino: "storing the password in the database is the proper thing to do" - I would disagree with that statement.Greenwich
I meant storing the password in the database as opposed to storing it elsewhere. Taking that sentence out of context makes it seem like I am supporting storing plain passwords, if you read the rest I obviously don't.Kilocalorie
@Paolo Bergantino: I understood what you meant perfectly. And I did not take it out of context. Best practice is not to store even the ecnrypted password, but to store a salted hash of the encrypted password.Greenwich
Not only is that what I said, I directed him to a plethora of posts that discuss salts and such further...Kilocalorie
@Paolo Bergantino: you sure there is not a typo in your post? It says "For most of the cases you are going to encounter (and I honestly can't think of any counter-examples) storing the password in the database is the proper thing to do." ??? It seems to contrdict your commentsGreenwich
What Paolo said directly contradicts itself. A salted hash of a password is not a password. Storing a salted hash of the password in the database is not storing the password in the database. The body of the answer is perfectly appropriate, but its first sentence is extremely misleading.Lovell
@Robert: That's getting dangerously close to a petty semantics game, but I'll fix it nonetheless...Kilocalorie
owasp.org/index.php/Password_Storage_Cheat_Sheet is a good reference on hashing/salting.Gyron
L
67

Background You never ... really ... need to know the user's password. You just want to verify an incoming user knows the password for an account.

Hash It: Store user passwords hashed (one-way encryption) via a strong hash function. A search for "c# encrypt passwords" gives a load of examples.

See the online SHA1 hash creator for an idea of what a hash function produces (But don't use SHA1 as a hash function, use something stronger such as SHA256).

Now, a hashed passwords means that you (and database thieves) shouldn't be able to reverse that hash back into the original password.

How to use it: But, you say, how do I use this mashed up password stored in the database?

When the user logs in, they'll hand you the username and the password (in its original text) You just use the same hash code to hash that typed-in password to get the stored version.

So, compare the two hashed passwords (database hash for username and the typed-in & hashed password). You can tell if "what they typed in" matched "what the original user entered for their password" by comparing their hashes.

Extra credit:

Question: If I had your database, then couldn't I just take a cracker like John the Ripper and start making hashes until I find matches to your stored, hashed passwords? (since users pick short, dictionary words anyway ... it should be easy)

Answer: Yes ... yes they can.

So, you should 'salt' your passwords. See the Wikipedia article on salt

See "How to hash data with salt" C# example (archived)

Lilybelle answered 28/6, 2009 at 2:22 Comment(10)
Nice post, except for one thing: md5 and sha1 have both been broken. You should probably go with a stronger algorithm, such as maybe the SHA2 family.Kilocalorie
Thanks Paolo -- you are correct. As the use of SHA2 is as easy as using MD5 & SHA1, please use the stronger hash algorithm.Lilybelle
SHA-1 hasn't been broken. But to paraphase Bruce Schneier: Walk, don't run, to SHA-2.Assess
"So, you should 'salt' your passwords"... But the salt is usually stored in the database along with the password, so how does that help? Te attacker simply has to add the salt to the dictionary attack phrases he is testing against. How is that more secure other than it won't reveal duplicate passwords?Extracurricular
@Lilybelle "You never ... really ... need to know the user's password" - that's a very short sighted assumption. There are many kind of applications where having a password stored in a way that can be retrieved is genuinely necessary. For example, an application that needs to frequently login to another system with stored credentials, supplied and updated by a user.Sanguinolent
@FranciscoZarabozo that's bad design of the both systems, because when my system is compromised, now my users on your system are too. oAuth and the like get around this, but you need the "other system" to support it. You should never reversibly encrypt a users password.Neptunian
@Neptunian Again saying "you should never"... Tell me, how would you store the credentials to access an API like a REST API for PayPal or Twilio or any other system that provides you with a user and key (that acts as a password)? What if your system interfaces with those APIs not only for you but for several clients? You NEED to find a way to secure such data and that way exists. Two way encryption methods serve a purpose, they are not there as a "bad choice". Bad choices come from how you decide to implement it.Sanguinolent
@FranciscoZarabozo PayPal uses OAuth 2.0 as the auth mechanism. If PayPal allowed you to store my PayPal pwd in a 3rd party app, it would be a disaster, as they have little control over every unrelated app's security. An OAuth token gets around this, and is not the password, so it's ok to store in a reversibly encrypted form. Nor is my PayPal pwd ever made available to the third-party system, as when I log into PayPal I'm on their website, not the third parties. That's how your system should interface with them. This discussion might warrant it's own question to ask if it's "ever OK"!Neptunian
@thinkOfaNumber: you should have a look at POP and IMAP and come back with the right way to authenticate on these services. Also ping Google about that as they are storing these credentials in gmail (when you need to access mail systems via IMAP or POP). Seriously - saying this just shows that you have not worked about real life APIs.Cuddy
@Cuddy Let's keep this technical and leave the guesses about my personal history for the pub. I admit that webmail is one case I never thought of, but POP and IMAP date back to the 80's when security was a different thing. Just because you can do it doesn't mean you should do it however, and I used to forward my POP mail to gMail so that I could avoid this very situation. PayPal would block your system from accessing them if you did the same, for good reason. A modern API developer should ensure that storing passwords is not necessary (or possible) by providing oAuth and other mechanisms.Neptunian
M
32

As a key-hardened salted hash, using a secure algorithm such as sha-512.

Mesic answered 28/6, 2009 at 1:59 Comment(2)
In my opinion, you should always use slow algorithms (like Blowfish, for example) to store passwords. This writeup is a much better answer: security.stackexchange.com/questions/211/…. Just putting it here, because this page still appears high in the search results.Euphrosyne
Following this advice for password storage would be doing it woefully wrong.Amersham
G
29

The best security practice is not to store the password at all (not even encrypted), but to store the salted hash (with a unique salt per password) of the encrypted password.

That way it is (practically) impossible to retrieve a plaintext password.

Greenwich answered 28/6, 2009 at 1:59 Comment(2)
Wayne, by salting before computing the hash, the rainbow table is effectively defeated, provided the salt is of sufficient size.Halutz
@Wayne Hartman: Not so. If the salt value is exposed, then you must generate a new rainbow table for that specific salt value. The point of a rainbow table is to have hash values calculated beforehand. And nobody will have a rainbow table for his specific salt.Assess
B
12

I'd thoroughly recommend reading the articles Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes [dead link, copy at the Internet Archive] and How To Safely Store A Password.

Lots of coders, myself included, think they understand security and hashing. Sadly most of us just don't.

Brown answered 28/6, 2009 at 15:8 Comment(1)
@Johan Looks like the link is now broken which is a shame. Here's an alternative codahale.com/how-to-safely-store-a-passwordBrown
P
6

I may be slightly off-topic as you did mention the need for a username and password, and my understanding of the issue is admitedly not the best but is OpenID something worth considering?

If you use OpenID then you don't end up storing any credentials at all if I understand the technology correctly and users can use credentials that they already have, avoiding the need to create a new identity that is specific to your application.

It may not be suitable if the application in question is purely for internal use though

RPX provides a nice easy way to intergrate OpenID support into an application.

Procambium answered 28/6, 2009 at 3:10 Comment(1)
I agree that openID rocks peoples faces off but for this application it is a in house database for a company I doubt they would like any old person coming in to log on. also web access is not needed for this app to work correctly so i would hate to require it.Arbour
G
3

In your scenario, you can have a look at asp.net membership, it is good practice to store user's password as hashed string in the database. you can authenticate the user by comparing the hashed incoming password with the one stored in the database.

Everything has been built for this purposes, check out asp.net membership

Gretel answered 28/6, 2009 at 1:56 Comment(0)
M
1

I would MD5/SHA1 the password if you don't need to be able to reverse the hash. When users login, you can just encrypt the password given and compare it to the hash. Hash collisions are nearly impossible in this case, unless someone gains access to the database and sees a hash they already have a collision for.

Mexican answered 28/6, 2009 at 1:55 Comment(4)
I wouldn't use MD5 for hashing - it's basically broken mscs.dal.ca/~selinger/md5collisionBrown
Actually, it's not that broken. What they can do is find the same hash value for two different files. What they can't do is reverse the MD5 and get a working password.Mexican
Well, wouldn't that be broken too then? You just enter the other password that generates the same hash, and you're in. You don't need to know the original password. The way to fix this is if you salt the password before hashing.Counterbalance
@Counterbalance if you add a salt to the password befor you use MD5 the collision doesn't matter because you can't use the other passwordTamishatamma

© 2022 - 2024 — McMap. All rights reserved.