So I've been looking at hashing passwords in vb.net and came across this thread (https://security.stackexchange.com/questions/17421/how-to-store-salt/17435#17435) and it showed about the salt only increasing the time to make brute force attack if the salt is known to the intruder as they need to make a new rainbow table. Could this be made more secure by making the salt a hash of the plaintext?
As an example to hash "plaintext" but adding a salt the string, this salt then being a hash of "plaintext" making "32nfdw213123" as example then hashing the total "plaintext32nfdw213123". In this case the salt is different for every value used but when used for verification doing the same process to a correct check string should produce the same salt and therefore the same hash value and verify. Is this actually more secure?
Thanks
TLDR: not really.
Longer answer:
Let's say some baddie has your database with all the passwords in it. He can now start brute-forcing passwords. Your goal is trying to make the brute-forcing as hard as possible.
So, theoretically, given that he has your database, he probably also knows how you're hashing your passwords (remember that security through obscurity is a bad form of defense). Your salts are no longer random, so our baddie can create a new rainbow table.
Let's say in database user password is encrypting in MD5 and it's no more readable by human, but i can copy MD5 hash and go to any website which provide MD5 decryption and get actually password. So am I missing something?
MD5 is a one-way operation (hashing), it is not possible to decrypt it. But you can hash a lot of passwords and check whether the hashes are the same (brute-forcing). When you find a match, you can not know if that was the original password though, because many other passwords result in the same hash (collisions).
Mitigating brute-forcing and other cracking techniques is the goal of password-hash functions like BCrypt, SCrypt, PBKDF2 or Argon2. Absolutely use them instead of MD5 and you will see, that there exists no websites offering "decryption".
I have big database with user and passwords in sha256 hash. Now I write new version and I want to use sha256+salt. Is there a way to convert same passwords with sha256 to sha256+salt and have no trouble with login?
Surely it is a good idea to make your password hashes more safe, but using a salted SHA-256 is the wrong way to go.
Best practise is to use a password hash function with a cost factor, which allows to control the necessary time to calculate a hash. Good algorithms are BCrypt, SCrypt, Argon2 and PBKDF2. In another answer I tried to explain how the switch to a new algorithm could be done.
The problem with the fast hashes like SHA-256 is the unbelievable speed of GPUs, one can brute-force about 3 Giga SHA-256 per second with affordable hardware.
The way to salt and hash a password is to take the plaintext password, add the salt to it and THEN hash it. When you have an existing password database already sha256-hashed you don't have the plaintext passwords, and you can't easily get them back in plaintext once hashed (which is a good thing).
What you could do instead would be to take the passwords in their current form, sha256 hashed, add the salt and then hash them a second time - or better: many times, with better hashing algorithms.
The function to verify the password would then repeat those steps to check that the password is correct. Assuming the second hash is just sha256-hashing once to make the example clearer, though it's not sufficiently secure:
step1 = sha256(plaintext_password)
password = sha256(step1 + salt)
If you really want to avoid working on top of your existing hash you could create a new table of users where you process passwords in the new way from the beginning, and then gradually migrate user's passwords over to the new table as they log in with their plaintext passwords, and remove them from the old table.
A third solution could be to deactivate all the old accounts and require them to change their passwords before they can sign in again, via fx. e-mailing them a link to change their passwords.
Makes sense?
That said you will get more qualified answers at https://security.stackexchange.com . For instance I just found this question on why salt->sha256 hashing once is insufficiently secure, and another one here on how to process passwords for more secure storage.
I am possibly taking over an app that literally just encrypts user passwords by doing md5( password )
They have ~2000 users to date. How can I migrate those passwords to a stronger encryption schema (e.g. involving a salt, user-specific hash, and their password, all encrypted with sha1, bcrypt, whatever)?
MD5 is a cryptographic hash function, not necessarily an encryption method. A hash is designed to only be performed in one direction, and cannot be reversed other than by dictionary attack. As an example, you can try out this hash database lookup if you're feeling frisky.
You will probably want to save these old passwords in a separate column, then when the users login to the "new" system, compare the MD5'ed version of that password with the old one, and if the digest matches, perform SHA1 with a salt on that password and store that in a separate column.
Alternatively, and probably a better approach, is the force the users to change passwords... and when they enter their new one, use the new hash algorithm on it instead.
We are currently storing plain text passwords for a web app that we have.
I keep advocating moving to a password hash but another developer said that this would be less secure -- more passwords could match the hash and a dictionary/hash attack would be faster.
Is there any truth to this argument?
Absolutely none. But it doesn't matter. I've posted a similar response before:
It's unfortunate, but people, even programmers, are just too emotional to be easily be swayed by argument. Once he's invested in his position (and, if you're posting here, he is) you're not likely to convince him with facts alone. What you need to do is switch the burden of proof. You need to get him out looking for data that he hopes will convince you, and in so doing learn the truth. Unfortunately, he has the benefit of the status quo, so you've got a tough road there.
From Wikipedia
Some computer systems store user
passwords, against which to compare
user log on attempts, as cleartext. If
an attacker gains access to such an
internal password store, all passwords
and so all user accounts will be
compromised. If some users employ the
same password for accounts on
different systems, those will be
compromised as well.
More secure systems store each
password in a cryptographically
protected form, so access to the
actual password will still be
difficult for a snooper who gains
internal access to the system, while
validation of user access attempts
remains possible.
A common approache stores only a
"hashed" form of the plaintext
password. When a user types in a
password on such a system, the
password handling software runs
through a cryptographic hash
algorithm, and if the hash value
generated from the user's entry
matches the hash stored in the
password database, the user is
permitted access. The hash value is
created by applying a cryptographic
hash function to a string consisting
of the submitted password and,
usually, another value known as a
salt. The salt prevents attackers from
building a list of hash values for
common passwords. MD5 and SHA1 are
frequently used cryptographic hash
functions.
There is much more that you can read on the subject on that page. In my opinion, and in everything I've read and worked with, hashing is a better scenario unless you use a very small (< 256 bit) algorithm.
There is absolutely no excuse to keeping plain text passwords on the web app. Use a standard hashing algorithm (SHA-1, not MD5!) with a salt value, so that rainbow attacks are impossible.
I don't understand how your other developer things 'more passwords could match the hash'.
There is argument to a 'hash attack would be faster', but only if you're not salting the passwords as they're hashed. Normally, hashing functions allow you to provide a salt which makes the use of known hash table a waste of time.
Personally, I'd say 'no'. Based on the above, as well as the fact that if you do somehow get clear-text expose, a salted, hashed value is of little value to someone trying to get in. Hashing also provides the benefit of making all passwords 'look' the same length.
ie, if hashing any string always results in a 20 character hash, then if you have only the hash to look at, you can't tell whether the original password was eight characters or sixteen for example.
I encountered this exact same issue in my workplace. What I did to convince him that hashing was more secure was to write a SQL injection that returned the list of users and passwords from the public section of our site. It was escalated right away as a major security issue :)
To prevent against dictionary/hash attacks be sure to hash against a token that's unique to each user and static (username/join date/userguid works well)
If you do not salt your Password, you're suspect to Rainbow Table attacks (precompiled Dictionaries that have valid inputs for a given hash)
The other developer should stop talking about security if you're storing passwords in plaintext and start reading about security.
Collisions are possible, but not a big problem for password apps usually (they are mainly a problem in areas where hashes are used as a way to verify the integrity of files).
So: Salt your passwords (by adding the Salt to the right side of the password*) and use a good hashing algorhithm like SHA-1 or preferably SHA-256 or SHA-512.
PS: A bit more detail about Hashes here.
*i'm a bit unsure whether or not the Salt should to to the beginning or to the end of the string. The problem is that if you have a collisions (two inputs with the same hash), adding the Salt to the "wrong" side will not change the resulting hash. In any way, you won't have big problems with Rainbow Tables, only with collisions
There is an old saying about programmers pretending to be cryptographers :)
Jeff Atwood has a good post on the subject: You're Probably Storing Passwords Incorrectly
To reply more extensively, I agree with all of the above, the hash makes it easier in theory to get the user's password since multiple passwords match the same hash. However,
this is much less likely to happen than someone getting access to your database.
There is truth in that if you hash something, yes, there will be collisions so it would be possible for two different passwords to unlock the same account.
From a practical standpoint though, that's a poor argument - A good hashing function (md5 or sha1 would be fine) can pretty much guarantee that for all meaningfully strings, especially short ones, there will be no collisions. Even if there were, having two passwords match for one account isn't a huge problem - If someone is in a position to randomly guess passwords fast enough that they are likely to be able to get in, you've got bigger problems.
I would argue that storing the passwords in plain text represents a much greater security risk than hash collisions in the password matching.
I'm not a security expert but I have a feeling that if plain text were more secure, hashing wouldnt exist in the first place.
In theory, yes. Passwords can be longer (more information) than a hash, so there is a possibility of hash collisions. However, most attacks are dictionary-based, and the probability of collisions is infinitely smaller than a successful direct match.
It depends on what you're defending against. If it's an attacker pulling down your database (or tricking your application into displaying the database), then plaintext passwords are useless. There are many attacks that rely on convincing the application to disgorge it's private data- SQL injection, session hijack, etc. It's often better not to keep the data at all, but to keep the hashed version so bad guys can't easily use it.
As your co-worker suggests, this can be trivially defeated by running the same hash algorithm against a dictionary and using rainbow tables to pull the info out. The usual solution is to use a secret salt plus additional user information to make the hashed results unique- something like:
String hashedPass=CryptUtils.MD5("alsdl;ksahglhkjfsdkjhkjhkfsdlsdf" + user.getCreateDate().toString() + user.getPassword);
As long as your salt is secret, or your attacker doesn't know the precise creation date of the user's record, a dictionary attack will fail- even in the event that they are able to pull down the password field.
Nothing is less secure than storing plain-text passwords. If you're using a decent hashing algorithm (at least SHA-256, but even SHA-1 is better than nothing) then yes, collisions are possible, but it doesn't matter because given a hash, it's impossible* to calculate what strings hash to it. If you hash the username WITH the password, then that possibility goes out the window as well.
* - technically not impossible, but "computationally infeasible"
If the username is "graeme" and the password is "stackoverflow", then create a string "graeme-stackoverflow-1234" where 1234 is a random number, then hash it and store "hashoutput1234" in the database. When it comes to validating a password, take the username, the supplied password and the number from the end of the stored value (the hash has a fixed length so you can always do this) and hash them together, and compare it with the hash part of the stored value.
more passwords could match the hash and a dictionary/hash attack would be faster.
Yes and no. Use a modern hashing algorithm, like an SHA variant, and that argument gets very, very week. Do you really need to be worried if that brute force attack is going to take only 352 years instead of 467 years? (Anecdotal joke there.) The value to be gained (not having the password stored in plain text on the system) far outstrips your colleague's concern.
Hope you forgive me for plugging a solution I wrote on this, using client side JavaScript to hash the password before it's transmitted: http://blog.asgeirnilsen.com/2005/11/password-authentication-without.html