I've seen a few other threads about this topic, but I can't seem to find a few answers to some questions involving the use of a random salt in password encryption. To my understanding, the steps go something like this:
Generate a random salt for the user.
Append the salt to their password.
Use something like SHA-2 to hash the result.
Store both the salt and hashed password in the database.
How does this method work when retrieving the user's password and verifying log-in? One response says that the user's salt should be retrieved, appended to their inputted password, hashed, and then compared to the stored hash, but doesn't this raise some issues? Namely:
How do you retrieve the salt without compromising that user? If someone wanted to brute-force a certain account's password, wouldn't they be able to retrieve the salt that was sent back from the server to hash the inputted password, thereby eliminating the security that having a salt adds?
If we avoid the previous problem by doing the salt retrieval server-side, then won't we be sending the user's inputted password unencrypted at one point or another (so that it may later be appended to the retrieved salt)?
The salt should never be exposed outside of the service - your instinct is right that this would be exposing the salt and introducing risk.
Any communication between your client and server should occur over an SSL connection - or at least using some kind of encryption of the interaction.
Keep in mind the purpose of the salt: to make it harder for someone to precalculate hash codes and therefore be able to look up passwords in the case of the database being compromised. An 8 bit salt makes the hash space 256 times bigger, making precalculation that much harder. The salt isn't about securing communication - there are other solutions for that.
You have to use random salt because of goal of using it is protecting against some types of attacks such as dictionary attack, brute-force attack and rainbow attack. thus it's so important to generate random salt for each password and store hashed password and salt in user table or attached to user profile. When you want to validate user password it's enough to hash entered password with stored salt and compare with stored hash value. I don't believe #cherouvim advise because it seems he doesn't care about above attacks. For more information i suggest an amazing, simple and understandable article by Defuse Security
Good luck.
I use a fixed salt (for all passwords) which is hardcoded on the application code. Assuming that the salt cannot be exposed (e.g via the UI of the application) this looks simple and good enough.
The only way to not send an unencrypted value which can be used to log in is to use SSL. If the hash gets sent to the server, the hash itself can be sniffed and used to log in. Do it server side.
+1 to what ruslik said about the salt. It prevents dictionary/rainbow attacks. A rainbow table for an average password + several bytes of random binary data would be astronomically huge.
Security introduced by salt is that you obtain hash for something much bigger and non-standard than the plain password. It doesn't matter if its algorithm is closed, because it protects the hash stored in plain in database from rainbow or dictionary attacks.
It's also reccomended to take hash several times recursively, maybe readding the salt at each iterations, so that brute force will take much longer.
EDIT: to what Bevan said about communication: usually the "number used once" (NONCE) scheme is used to transmit passwords over unsecure channels. The server gives a random string never used before to the client, he appends it to the plain password, computes hash, and sends it. This protects you from eavesdropping attacks.
Hashing passwords protects against plainly visible passwords, and salting them guards against dictionary attacks. As far as protecting passwords during transport, I would recommend SSL/TLS.
Related
I have to create a simple security program that is about storing of passwords and the use of authentication mechanisms. I'm just not sure about what to choose from three selections and why it's better/worse over the others.
To me everyone can be seen secure, if it's done right, some are just easier and a lot faster to implement. The three possibilities I have are:
Storing passwords in a system file where the operating system will handle the confidentiality and integrity. (Not quite sure how this can be done, as I haven't storing anythings in a system file before)
Storing passwords in a public file in the program where passwords are hashed + salted (salt is uniqe for every password hash generated)
Storing passwords in a database and let the dbms handle the protection.
To me the best way if you should handle multiple clients signing up with a username/password, the best way is to use the database where also passwords a hashed + salted in it.
Can any of you make some comments how it can be done/pro/cons?
It is not so much about where to store the passwords, it is rather about how you store them.
If you can store hashes, because you only need to verify the passwords, then you should absolutely use slow password-hash functions like BCrypt, SCrypt, PBKDF2 or Argon2, most implementations add a unique salt on their own.
If you need to retrieve the plaintext passwords, because you must login into a 3rd party system, then you should take all possible measures to protect them (encrypting the db/file, require access privileges). The most safe solution is, when the user enters a master key whenever he wants to access the password storage, so the system itself is not able to decrypt them.
I am making a program in C that allows the user to register and login. When the user registers I want to save his username and password in a file.
As I understood it, the best way of doing so is adding a random salt to the end of the password and then store a secure hash (SHA-1 for example) of the salted password.
My question is: If I locally store the username, hash and salt in the text file, what prevents an attacker from just changing the hash and salt in the file to his own SHA-1 hash with his own salt and then log in using his new password?
Thanks.
It depends on whether the attacker has only access to this password file, or if he has access to the executable as well. In the latter case you can only make it harder to exchange the hashes, but you cannot entirely prevent it.
For the first case, on can use a HMAC to verify the stored hash:
Your application would then contain a secret strong key, and would calculate the HMAC of the hash with this key.
This HMAC can be stored together with the password hash in the file.
When reading the hash for verification, the software calculates the HMAC again and can compare it with the stored one.
An attacker won't be able to produce the correct HMAC for his own hashes, as long as he doesn't know the secret key in your application. So what we gain is, that the password file cannot be altered but by your application, the security is concentrated into the key of your application. The same can be achieved with encrypting/decrypting the password file.
P.S. Please do not use SHA- to store passwords, instead use a hash function with a cost factor like BCrypt, PBKDF2 or SCrypt.*
It seems you have only one single server in place, which hosts the application, but also the username and hashed password. In this configuration, there is no perfect protection against an attacker being root.
However, you can try to have some good features:
The hashed password makes it hard for an attacker to get the password and use the application with the user's credentials
however, an attacker could indeed change the hash. To prevent that, you could try to protect that file, either by:
detecting changes comparing with a remote copy
or use a signature on it: basically, allowing only your application to update password. You can have a secret key in the app, used to sign the file, and add the signature at the end. When the app reads the file for authentication, it can check if the file was corrupted or not. It's probably going to be hard for the attacker to get that signature mechanism, but nothing impossible of course.
I know this topic has been discussed a million times. But it's new to me and the more I read about it the less I understand what's actually happening or supposed to happen.
I add a per-user salt to the hashed storage of a user's password, so the stored password hash looks like this: hash(password + perusersalt).
This results in same passwords of different users being stored as different strings in the DB. Cool. But I'm not worried about someone breaking into the DB and looking up the hashed passwords. I'm worried about someone brute-force-querying my server for combinations of username and password. In this case the salted and hashed storage of passwords is useless, because the correct combination of username and password will yield a successful login. Right?
Am I correct under the impression that in this scenario the salt is pretty useless? Because the server only accepts username and password at the interface (no salt transmitted), a normal dictionary attack will do, right?
So the salt is only there to obfuscate the password of a user (obtainable only by reverse Rainbow Table lookup) from someone who has access to the DB. Hmm.
Related: My web app doesn't even transmit plain passwords. Passwords are already hashed client side, only to entirely reject responsibility about someone's stolen passwords, and the whole thing uses SSL.
Does this mean I'm more or less at the highest possible security level, because correct combinations of username and password must of course yield a successful login?
Thank you for clearing up the mess in my head.
You are correct in your assumption about the brute force attack. If the user has a simple password, the salt and hash won't really matter. The dictionary attack will guess "password" and allow the attacker in. You have to require a secure password from the user, then do the one-way encryption (hash it with the salt), and use SSL like you are.
"Passwords are […] hashed client side […] to […] reject responsibility about someone's stolen passwords, and the whole thing uses SSL."
Does the client send hash(password+salt) ?
With this design, a client does not really need the password in order to login successfully, it only needs the hash. So you might still be responsible for leaking the real password (the hash).
I need a login system to check the user password.
I know about salting passwords, but should I store the salt and the encrypted password or should I only store the encrypted password and the salt is somewhere in my app config file?
Please pro and cons if there are some, thanks!
It depends on how you are using salts for encryption...
If the salt does not change frequently:
I would store the salt alongside the master key in a safe location. Storing it alongside each password would just constitute in a lot of redundant data. Furthermore the database is probably not as safe a place as the storage location of the master key. Mind that the salt may be an essential part of the password security. (Depending on lenght and strenght of passwords chose by the users...)
If the salt changes frequently, i.e. with every encrypted password:
In this case you would need to store a huge number of salts. As one salt is only useful for the decryption of one password it's not as critical a piece of information as in the above example, storing it in the DB alongside the passwords is ok I guess. At any rate, storing the salts in a the app config could get messy. (Unless you would create an special salt database or something like that.)
If you have differing salt for every password then you will have to store the salt and hashed password in DB itself. If you are using only one salt for all passwords, then you can prefer to store them in other location kind of config file.
I'm currently working on basic user authentication for an app I'm putting together, and I don't have much experience with security.
This said, I understand the practice (and necessity) of salting/storing a (salted) password hash in a database as a blob, as opposed to the password (encrypted or no). I've already implemented this.
Is there anything to be gained by salting/hashing a user name and storing the hash in the database, as opposed to the username in plain-text (or encrypted)? It strikes me this would make it quite a bit harder to determine which users may access the system using the database for authentication.
Since it's vital to make it difficult for someone to crack the password for a user account, wouldn't it also make sense to increase the difficulty for determining which users are viable?
Edit: it's possible some of the language I'm using isn't 100% correct: feel free to correct :-)
Edit2: I changed one of my first points to indicate salting hashes -- thanks everyone for pointing out that I missed this :-)
Edit3: Removed wording indicating I am encrypting/decrypting a password. I'm using salted hashes and am storing that in the DB -- thanks Scotty for pointing this out.
It depends on the context
It's important to assess the sensitivity of the material you're serving. To dig deeper, I'll provide a few use cases.
Scenario 1: A social networking application
All of your user's interactions happen in the public. Their email address will be used as their username. There username is not considered private because their name appears in all their posts. The username may be searched by other users and/or email invites are enabled.
Verdict - Hashing = Bad
Scenario 2: An E-Commerce site
The user may or may not participate in public interactions (ex. commenting, reviews). Using an email address as the username is probably a bad idea because, through the use of password recovery, a compromised email account means a compromised user account on your site.
There is a lot of gray area here that is typically exploited for 'convenience.' If your site uses email as the user name, stores shipping history, and credit card numbers; a compromised email could mean a lot of identity theft troubles for your user.
In this case, using a policy where the username is not the user's email address is probably a good idea. Hashing the email adds no value.
Note: I'm looking at you Amazon.com.
Verdict: Common Practice != good practice
Scenario 3: A porn site
Make the username a pseudonym and the login name the user's email address. They may feel inclined to talk about the content and don't necessarily want their name to show up on Google's results for a smut site.
Assume the worst here. If somehow your database is hacked, the exposing of your user's identities could cause irreparable harm. Don't think this could happen to you? Take a look at this article.
Not only are their user's accounts hacked and passwords exposed but, there's a good chance a lot of those users used the same password on their email accounts. Now their info is posted anonymously on PasteBin for the whole world to see. Even worse, most of them probably don't even know this has happened yet.
By simply hashing both the username and password, they would have saved themselves and their users a whole lot of trouble.
Verdict: Definitely hash the email address whether or not it's used as the username.
Scenario 4: A bank
It should go without saying that no expense should be spared when it comes to banking/financial sites.
Security can be increased by:
Using a username other than the email address
Forcing a unique username by requiring numbers and letters
Hashing passwords
Requiring 2-point authentication (in case the user's email password is compromised)
Hashing email addresses
etc...
No expense should be spared to protect your users because, to not do so, means you're gambling with their livelihood.
Conclusion:
There is no hard and fast rule for security that applies to all sites. In some cases, the username is made public so hashing it adds no value. In others, not hashing it could cause irreparable harm. If you do end up developing a site where a username/email hash could be made useful here's a good approach.
Hash the username
Generate a unique salt for the user
Hash the password using the salt
Store the password with the salt in the database
By not hashing the username with a salt you avoid the chicken/egg problem. Unless you use a static salt for all of the usernames.
Keep in mind that a static salt for all the user accounts may be found out by reading the code. Once a static salt is found out, it'll essentially be useless when a rainbow table attack is employed. If you salt the passwords, generate a dynamic salt and store it along with the rest of the user's credentials in the database.
If you want hard/fast rules for simplicity here are a few good assumptions to remember:
Assume your database may be compromised at some point
Assume your source code will be compromised at some point
Assume your user's email will be compromised at some point
Assume your user's are dumb and use the same password for your site as they use for their email
Assume that hackers are smart/resourceful and financially driven.
If you choose to store sensitive/private data, then going the extra step may save you a PR/legal nightmare in the future.
Update:An interesting article about seed hashing just showed up on Coding Horror.
Short answer: most likely no.
Long answer: Your situation seems to lack the key "my usernames are sensitive because of ..." which raises the question: "Why? What is the specific, demonstrable problem that protecting usernames would solve?"
Without that problem, what you are describing is a common pitfall in security-related development (and really development as a whole): coming up with some idea to secure or obfuscate some part of the system, and then searching for a reason to use it. As with anything in software development, you should avoid doing anything other than exactly what is needed until a clear problem presents itself that can only be solved by using a specific tool.
Extra hint (for free!): salt your password hashes. Plain-old hashes are far less secure.
If you salted & hashed the username, you'd leave yourself with a bit of a chicken & egg problem.
If you salted & hashed the username, how would you find it in the database? You'd need to look up the user's record to find the salt you used to hash the username...
Probably not. Think of it this way - the username is the application's way of figuring out which account a user is trying to login as. The password is the application's way of figuring out whether the user is actually allowed to login as that account. In practice, this means you're going to look up a row in your accounts table using the username as an index. By encrypting the username, you're simply making it harder to find the right row.
However, if you're using the same encryption scheme to encrypt the username and password, they are pretty much equally secure - if you can break one, you can break the other. Thus, encrypting both makes it harder to lookup the user, but doesn't add any additional security.
Note: In your question you talk about decrypting your password field. You probably want to make this impossible (literally). Most people encrypt their passwords using a one-way hash function of some sort (MD5 and SHA256 are popular), along with a salt. The "one-way" part simply means that once you run something through the function, you can't use what you get out to get what you started with. However, if you start with the same input, you'll always get the same output. The salt is a secret that only your application knows (sort of like an encryption key), which is added to whatever you are encrypting, before it is run through the one-way hash. This makes it impossible to do things like match two encrypted passwords from two different sites (assuming they're using different salts).
It's not very fair to your users to store their password in plain text since everybody that has access to your database can see their passwords. You should use a salted hash.
Salt_(cryptography)
You can never properly evaluate the security of a system by looking at a single part of it in isolation. Whereabouts are you storing the key to decrypt the passwords?
Do the people that have access to the database also have access to the location you are storing the encyption key? If so you've only gained a minor improvement in security by encrypting the passwords and probably nothing much more to gain by encrypting the usernames.
If the decryption key and program using it are more secure than the database - which is pretty unusual, normally the database is in the most secure spot possible - then there would possibly be additional benefit to also encrypting the username as you'd be depriving attackers of useful information in brute force attacks.