RDBMS Cryptography [duplicate] - encryption

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
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

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):
How to best store user information and user login and password
Best practices for storing database passwords
Salting Your Password: Best Practices?
Is it ever ok to store password in plain text in a php variable or php constant?
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.

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)

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

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.

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.

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.

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

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.

Related

Saving decryptable password

I know there was question like this million times, but I was unable to find answer that will fit my needs.
I'm building something like small internal password manager for my company, to store login data for various servers and so on.
When new user is registered, his password will be saved in database in salted/hashed version so no one can get access to it (and for that part I think it's all ok, correct me if I'm wrong).
But then, when user is logged in, he is able to add new server with it's login details.
Question is, how to store those.
Because, at some point, I have to present this login details to user in plain text (that is whole point of this application).
Best I could came up with is using some kind of symmetric encryption.
Idea is that app will crypt login details with symmetric encryption and save it in that way into database, and then when data is needed once again will extract data from database, decrypt it with same key and present to user (and key should be in source code of application?).
It could be asymmetric encryption but it's the same if public and private key are stored in same source code, then there is no any benefit of using it?
That doesn't seem too secure, but I can't think of anything better.
Is there any better way to do this, to store this login data?
If it's important to you, application will be in PHP and database is Oracle
I would just use symmetric encryption. The standard steps are:
Derive a symmetric key from a user-supplied password (e.g. PBKDF2 or scrypt)
Encrypt the data using AES-128-CBC or better with a good random IV
HMAC the result (e.g. HMAC_SHA256) or just use AES GCM mode
Store IV+ciphertext+MAC in the database.
This can all run in a browser these days (see crypto-js and aes-js). That way the server never gets to see the plaintext password (not sure if this is a requirement).
The MAC can also serve as a password hash, i.e. if the MAC validation fails, then it means the supplied password is incorrect.

Dilemma of choosing either to hash or encrypt passwords

After reading some posts and articles online, it seems that most, if not all, people suggest using some sort of hashing algorithm for keeping a user's password safe, since you cannot unhash it, which is good, but that's where I begin to have a problem with my situation.
Right now I am in the early stages of modifying the way we secure our users' passwords. We currently store the hashed passwords in our MySQL DB using Sha512. With my current understanding, although hashes may be secure in the sense that they cannot be reverse (or at least not so easily), it is also insecure in that there are possible collisions, since a hash has a fixed length no matter the size of the original input, which limits the number of possible hashes, causing a possible Pidgeon Hole problem.
Now comes another part that I have a problem with, especially for my case.
I am trying add some features to our users' password where the user cannot enter a new password if it is too similar to, say, their last three passwords. Ex: if their last password was password1234 and their new one is xxxpasswordxxx, then it would fail. However, from my understanding, it is not possible for me to add this feature since I have no way of unhashing their previous passwords to check if any substring in their old passwords are in their new password. This brings me to the whole encryption/decryption part.
I have been looking at AES 128 using a CBC encryption mode and it seems like a solid choice, since I don't really care much for parallelization in the encrypted portion. Additioanlly, by using an encyption route instead of a hashing route, I can actually do that check to see if their last three passwords are similar to their current one! BUT, there is the whole problem of being able to see the users' plain text password in the first place.
Additionally, I have been trying to think of a way to use unique keys for every single password without storing it in our DB because I feel that is way too insecure. I could just use a static randomly key for ALL passwords, but I am not sure if that is a good idea either, even if I use unique IVs for all the passwords.
So to sum up my situation is this:
I want to be able to prevent the user from entering a password similar to their old one's, in addition to actually improving the security of our password storage. From the knowledge I have at the moment, I can either continue storing the passwords as a hash, but I won't be able to do the similar password check OR I can encrypt the passwords instead, which is something that is frowned upon.
I am clearly not an expert in this and I know for a fact I need to do some more research, but I want to make sure I am starting in the right direction.
Regarding the second paragraph: hash collisions are absolutely NOT a problem. For which attack scenario do you think that is a problem? You should really stop throwing buzzwords around, especially regarding security.
You are partially right that your feature idea would fail. And that is a good think because the idea is bad. Why do you want that "feature" - it will only annoy users and cause people try to circumvent your restrictions using numbers at the end including the month or some other incrementing from version to version.
And encrypting passwords is bad - period.
As soon as you can decrypt them, an attack can as well - end of story.
Personal experience of pretty much the scenario you are describing: The client has a tool where you are forced to change the password every 2 months, I am currently at "password"10. I am doing exactly what everybody is warning about when forcing password changes every X months - simply altering the same password piece by piece. I have a very good password (15+ characters, upper and lower case, numbers, special chars) plus a system for choosing a password for whatever site I am setting an account up for. Forcing me to change my password breaks my "system" because now I can no longer generate the password in my head over and over again because the outcome will not match what the site has forced me to set up after the first two months. If the site would start introducing some password similarity restrictions I would probably start writing them down.
Why not keep using hashing, but require that the user enters his or her old password when changing to a new password, that way you can authenticate the old password to authorize the password change, then compare the plain-text versions of both for similarity before proceeding with the change?
when you keep hashed passwords, you can not check for similar passwords, but you could prevent them from reusing a password they used before. By keeping the old (hopefully salted!) passwords, you can compare hash(new_password + old_salt[i]) with the salted_hash[i] of the old password. If they are the same, the user is reusing an old password.
I totally agree with the others that hash collisions are not a problem. You are planning to use SHA512, that is 512 bits of randomness the attacker has to compete with. The only way you could break that is by using rainbow tables and you protect yourself against them using the salted hashes (i.e. even if the password is the same, the salted hash will result in different hashes; it is not a problem if the attacker gets to know both the salt and the hash, so you can store salt + salted_hash in one location).
For security reasons I'd ditch the "similar password" thing altogether. If the attacker gets a bunch of passwords, changes are that there are a lot of bad passwords in your database. Using heuristics and dictionary attacks he will have a good change to guess your encryption key --> immediately unlocks all passwords of all users.
The only safe way for passwords is if the operator of the system storing them cannot recover them either. Anything else is just the next 0-day bug waiting to be exploited.
currently store the hashed passwords in our MySQL DB using Sha512
SHA-512 is too fast. Any attacker gaining access to your password hashes can very quickly run their password guesses through your hash. You need a slow algorithm so each guess takes them thousands of times longer. But as you need to hash these passwords too, you need to choose a value that won't overload your system, or arguably even worse, test your users' patience. Use either bcrypt (on its own) or PBKDF2 in combination with your SHA-512 (although SHA-1 HMAC is more than enough).
it is also insecure in that there are possible collisions
The collision resistance of SHA-512 is not a problem until you are approaching 2256 users within your system. As there are not even close to that number of people on the planet, I can safely say your system will be fine.
Dilemma of choosing either to hash or encrypt passwords
If you need a reason to go with the former, have a look at the details of the Adobe breach. They were encrypting passwords instead of hashing. TLDR; disaster. If your system is even moderately sized, you don't want anything like this being presented by the media regarding your system. Do things properly - use PBKDF2 or bcrypt - that way you are looking after your users using industry accepted methods and cannot then be criticised for your password storage scheme.
by using an encryption route instead of a hashing route, I can
actually do that check to see if their last three passwords are
similar to their current one
Well since the user will (hopefully) be entering their previous password as an additional authentication check in order to change their password, you could compare their passwords at this point as you will have them both in cleartext. For example
old password != new password
lowercase'd letters in old password != lowercase'd letters in new password
adding up all numbers in new password > adding up all numbers in old password + 2 || adding up all numbers in new password < adding up all numbers in old password - 2
And maybe some other rules you wish to define to prevent password similarity. If these rules are applied between changes from the first password to the second, and then the second password to the third, the user may get used to your rules and may be less likely to make their third password too similar to their first. You could also keep a password history table storing the bcrypt hashes of their previous X passwords (e.g. four), and do an absolute comparison to ensure they are not switching back to one they have previously used. I wouldn't keep more than four just in case any of their previous passwords are weak enough to crack and have been reused on other sites, because any breach on your system could potentially expose them, and also as mentioned checking these will be a slow process. You could however, going forward ensure that the user doesn't choose any password that has been involved in any breach by loading common passwords into a blacklist on your system.
Encryption of passwords is a bad idea, and the security benefit of fuzzy matching on all previous passwords does not outweigh the security risk of having two-way encryption active (in my opinion).
To keep password in a secret manner, you have to hash the password plus a salt.
For each user, you randomly choose a salt, you keep in database the salt for each user.
You store in database hash(password+salt).
When you have to check user's password, just add the salt, hash both and check against database.
If a user change the password, you can change the salt as well.
Aftewhile, you may choose an algorithm or another depending of the security level, SHA2 seems to be a good start.

encrypting passwords & crypto questions

I've read a few articles about encrypting passwords and what I read seems that bcrypt is the way to go.
I know hardly any about cryptography, does it make any difference from the security point of view if I add the username to the password and hash that?
Also does it make sense to create a salt for each user? If my db would get leaked those salts would also be there, should I encrypt the salts too with a global salt?
Does it make sense to also encrypt the user's email adress?
Anywhat what I planned to do is:
+use bcrypt
+allow all characters in passwords
+force User to use a digit and special char in his password
+set the minimum password length to 8 chars
I'm not building an app which requires mega high security standards but I would like to offer my users some seriouse protection in case my DB gets leaked somehow. ( hopefully it won't )
does it make any difference from the security point of view if I add the username to the password and hash that
No added security, especially if you are already using a SALT. Has the drawback that you have to rehash and persist the hash each time a user changes their username.
Also does it make sense to create a salt for each user?
Yes, this is commonly done.
If my db would get leaked those salts would also be there, should I encrypt the salts too with a global salt?
No, do not encrypt them. The purpose of the SALT is just to force the attacker to have to perform a new brute force search for each user/password, instead of one brute force attack for all.
Does it make sense to also encrypt the user's email adress?
No. Unless you have some (strange) business requirement for that.
Kudos to you for asking the question before implementing. Unfortunately, that's the best point of optimism I have for you.
Security is hard to do right. Very hard to do right, in fact. If you don't know much about it, then don't try until you do. In the meantime, use a proven infrastructure that does this for you in the (hopefully) correct fashion. There should be one available for whatever framework you happen to be using, and if there isn't, that may be reason enough to switch.
That said, dont use the username for the salt, and don't bother encrypting the salt. You should also not be encrypting (or hashing) the user's email address, unless you or anyone else will never need to know it (as the maintainer(s) of the system). And adding the username to the password provides no benefit, and has several drawbacks, so don't do that either.
As far as a unique salt - this is a must. Without it, you might as well not have one. Read up a bit on encryption, hashing, and salting (and peppering) before proceeding. Even better, use a library that already does it for you as mentioned before.

How can I encrypt data with a password, but allow said password to be reset

I'm asking at a purely abstract level (no code required).
Some data is to be stored on a web-server/database on behalf of a user. The data is encrypted using the user's password as the key, ensuring that if the server or database is compromised, it is relatively useless to the attacker.
The problem is that the standard process of resetting a user's password (sending them a link with a token) won't work, because there is no way to decrypt and re-encrypt the data without knowing the previous password.
Are there any other ways around this?
When you say that you are willing to reset the password using some piece of automated authentication, then what you're really saying is that there are two passwords: the "normal" password and the "authentication" password. The solution to your problem is to encrypt the file using a random key and then encrypt the key using each of the passwords.
As a concrete example:
User provides a password "Aw3som1"
User also provides his high school mascot: "the Chipmunks"
Just to make it really complete, let's assume your authentication scheme is very forgiving like many are. You would accept just "chipmunks" (or "CHIPMUNKS" or maybe even "chipmunk") rather than "the Chipmunks." But whatever it is, your scheme must be deterministic. Every possible answer you will accept must resolve to the same hash. In this case, I'm going to assume that you lowercase the security answer, remove articles, and reduce to singular if it's plural. Then you prepend the class of question. So your secondary password is something like "mascot:chipmunk".
You now make up a random 16-bytes and use that key to encrypt the data. You then use normal password-based encryption techniques (e.g. PBKDF2) to encrypt the key with each of your passwords above. Then you throw away the key and the passwords.
When you need to do a reset, decrypt the real key with the provided password ("mascot:chipmunk") and re-encrypt the key with the new password (and "mascot:chipmunk" again).
The one usability issue is that a password reset invalidates all the other security answers, and the user must reconfigure them all. If that's a problem, you could put all the security answers into a bundle and encrypt that using the same technique as the data. (i.e. the security answers are encrypted against all of the security answers.)
This approach of course creates two (or more) passwords that can unlock the data, and so dramatically drops brute-force search time. You should consider that when scaling things. That said, your safety margins should generally be several orders of magnitude, so even a few passwords should be workable for many situations. Remember also that the security questions live in a tiny key space, particularly things like "mascot" or "make of car" which probably only have a few dozen likely values (unless you went to my high school which had a truly bizarre mascot…) That just means that aggressively tuning PBKDF2 is even more important.
Of course the existence of any kind of password reset system is going to make targeted attacks much easier. But that's true no matter how you implement the encryption.
But what if there isn't even a security question? What if you'll reset the password based on an email address alone? Well, then the email address is the password. That's problematic in the face of a stolen database, and it's hard to fix because there is no real secret (and encryption requires a secret). But all is not completely lost. One thing you can do is to never include the actual email address in the database. Think of the email address as a password (since it is in this case). Store a hash. You can't use a random salt on it, but you could still use some single salt for the whole database.
So my email is test#example.com. You treat that as a password, salt it with "mygreatservice" and run it through PBKDF2. To login, just treat it like a password again.
An attacker, though, has to guess email addresses one at a time. That's not incredibly hard, but he can't just decrypt the entire database in one go, and he'll never get the data from emails he doesn't guess. (And you did choose a really easy reset mechanism.)
Why do you need to un-encrypt the password? If they have forgotten then you will have to verify them based on the fact they had access to the email account where the reset token was sent. Ideally you would include some other form of question/proof of identity on the reset page like a secret question.
Also, you're best not storing the password using reversible encryption but instead using a strong salted hash which is one way.

Hashing vs. Encrypting Passwords

I'm using ASP.NET membership for a site that will serve primarily sophisticated users. I understand the difference between hashed and encrypted passwords, and I'm trying to decide between the two.
After my last client complained bitterly about hashed passwords being a total PITA, I've started to favor encrypted passwords. But someone suggested this just isn't secure enough.
So my question is: What, exactly are the risks of encrypting passwords? Any person with the ability to steal passwords by decrypting them from the database would surely have the ability to reset them if they were hashed, no? I'm having trouble seeing where someone could cause trouble with encrypted passwords but couldn't with hashed ones. Making it convenient for users is also important.
The risk with decryptable passwords is that people use the one password for various logins and accounts, not just for the application you are dealing with.
With an encrypted password, a
stolen/decrypted password could be
tried out on users' other accounts (e.g. a stolen banking password could lead to access to their email).
With a hashed password, there is no
recovery. Theft of password hashes
should never easily yield usable
passwords
Treat passwords as the property of the account owner. It's not yours to view, decrypt, or do other things with. If a user forgets their password, offer reset, and not retrieval.
The point is that Encrypted passwords can be decrypted...so it is possible that with having access to the keys etc all the passwords could be known.
Hashed (with salt) passwords are a 1 one function so there is effectively no possible way of determining what the password was which means the user supplying the password has less to worry about. Sure someone could change the hash in where ever it is stored (e.g. database) so that user could no longer log on, but the password they had provided originally still wouldn't be known.
Edit
As you've tagged the question ASP.Net, I'd recommend using BCrypt.Net library to generate your hashes
The risk is, that encrypted passwords can be decrypted to get the plain text password.
Hashes normally can't be reversed.
Reversing an MD5 Hash
A quite common occurance is people using the same username and password on all their internet sites.
All it takes is one site password to be decrypted, and all the users sites are at risk.
While with a hash, the cracker never gets the plain text password.
As other users have said, encrypted passwords can be decrypted and are not a good idea.
If you use a standard hash technique the user who has access to your database could put in the standard md5 for "password" for example. You can solve this issue with a salted hash which takes the input string and a salt string value to create a unique hash that can not easily be replicated. Store it somewhere safe and use sha1($salt . $input). You now have a salted hash.

Resources