Password Hash Approach - security

I need to store the hashed password in the database the first time the user registers into the system. The standard approach is to take the Password and a salt, append them and use a hash algorithm whose output is saved in the database.
I am going to use Cryptographically Secure Pseudo-Random Number Generator(CSPRNG) for generating the salt. The salt generated using CSPRNG are very secured for generating salts as I have read from sources Link. Since the salt is very difficult to predict, using the MD5 for hashing the final String(Password || salt) is a good decision or is there any better alternative ?
NOTE:
The parameters I am considering for choosing a Hash Algorithm:
1) The security should be considerably good.
2) The hashing algorithm should be fast enough to not hinder the user experience.

This has been covered time and time again all over the internet, but here we go, once more...
Use bcrypt, argon2 or PBKDF2. Use a CSPRNG to generate a salt. Storing the salt with the hash is fine. Don't use MD5, SHA256, or anything else without an intentional iteration count.

Related

Why can't we store every hashed password ever in storage(HDD) and use that to match the hashed password instead of use brute force password cracking?

So let's say we somehow got the hashed password of a victim.
So the brute force approach is to take every possible string, hash it and check if it matches the victims hashed password. If it does we can use that string is the password and hence hacked.
But this requires a great deal of computational power and good amount of time even for strings with 6-8 characters.
But what if we can hash every possible string with less than 10(some) characters and store it in storage like a sorted database before hand. So that when you get the hashed password you can easily look up the table and get the password.
P.S:-
For this example let's say we are working with only one type of hashing algorithm and have huge data servers to store data.
I'm new to security and this a very very basic question but for some reason the answer to the question was really hard to find on the internet.
This is called a rainbow table, and is very much a known concept.
It is also the reason you should never just store the hash of passwords. A salt (a random string added to the password and then stored with the hash as plaintext for verification) can easily mitigate this attack by effectively making it impossible to use a rainbow table and force recomputation.
Also just for completeness it's important to note that plain cryptographic hashes are not adequate anymore to be used for credentials (passwords), because they are too fast, which means it's too fast to generate a rainbow table for a given salt, effectively bruteforcing a password. Specialized hardware makes it feasible to recover relatively strong passwords if only hashed with a plain crypto hash, even if using a salt.
So the best practice is to use a key derivation function (KDF) to generate your password hashes in a way that makes it very slow (infeasible) to brute force, but fast enough to verify. Also in most known implementations adding a random salt to each hash is automatic and the whole thing is just secure.
Such algorithms are for example PBKDF2, bcrypt, scrypt or more recently, Argon2. Each of these have different characteristics, and are more resistant against different attacks.

One way functions, Hash algorithms

Basically One-way functions have two properties:
1. Irreversible
2. Collision-Resistance(which means no two same words have the same hash value correct me if im wrong)
On the other hand i see that Salted Hash Passwords are used to provide more security to hash values of passwords and also provide collision-avoidance to passwords which have the same plain value.
So why does this happen, aren't hash functions supposed to have Collision-Resistance, why does Salt have to provide this when hash functions already have that property?
Thank you in advance.
It would be wonderful if one-way hash functions were really one-way.
What happens if two users choose the same password? Without salt, they get the same hash.
Guess what? People are not good at choosing passwords. These creatures of limited memory and lacking in natural internal cryptographic randomness often choose passwords that are short, low entropy, and brute-forceable.
If you want to crack the hash of a password that didn't involve salt, then just Google it.
Salt helps fix the problem, but it is not the panacea. With salt, two people who choose the same password do not get the same password hash, assuming the salt is different for both users. Salts also help prevent rainbow table attacks, which is a time-memory trade-off to hack out passwords.
Still, this does not solve all problems. If your database becomes public, salt + cryptographic hash is not enough because attackers can still brute force-passwords using low cost GPUs.
So what is the solution? You not only need salt, but you also need brute forcing to be a slow process. That's why we don't use hash functions for passwords, instead we use password hashing functions. Don't blame me for the stupid terminology, I fully agree. Bottom line: choose from bcrypt, scrypt, argon2, pbkdf2. I personally recommend bcrypt.
Just want to add a detail to #TheGreatContini s answer.
For passwords hashed without a salt, you will probably find an
already prebuilt rainbow-table.
If you use a single salt for all passwords, an attacker has to build 1 rainbow-table using this salt,
to get all passwords.
If each password gets its unique salt, an attacker would have to build a rainbow table for each password. Building a full rainbow-table to only get 1 password doesn't make sense, that's why we can say that unique salt prevents rainbow table attacks.

How does every system or server get a different hash function to store passwords

as I understand it, user passwords must be stored as hashes instead of encrypted, because an attacker cant deduce a password from its hash, while he can deduce a password from its encryption, if he gets access to the encryption key.
Now, obviously every system must use a different hashing function to hash its keys. My question is, how do they create these different hashing functions? Do they use a standard hashing function and prime it with a big key? If so, wouldn't an attacker be able to deduce the passwords if he got access to this key, making it the same as encryption?
Cryptographic hash functions are always non reversible, this is their purpose. Even discouraged "unsafe" function like MD5 and SHA1 are not reversible and they don't need a key. The problem is that you can find possible matching passwords too fast with brute-forcing (more than 10 Giga MD5/sec).
The "big key" you mentioned is probably the salt. You generate a random salt and use this salt in the calculation. It is safe to store this salt together with the hash, because its purpose is to prevent the attacker from building one single rainbow-table and finding matches for all passwords at once. Instead (s)he must build a rainbow-table for every salt separately, what makes those tables unpracticable.
The problem with the speed you can only overcome with iterations of the hash function. A cost factor defines how many times the hash is calculated. Recommended algorithms are BCrypt, PBKDF2 and SCrypt.
Now, obviously every system must use a different hashing function to hash its keys
No, they don't.
If your password is s3cr3t, then it will have the same hash value in the database of a lot of servers, sadly likely A4D80EAC9AB26A4A2DA04125BC2C096A
The way to make this suck less is to generate a random code per password, called a salt, so that the hash of s3cr3t on server 1 is likely to be different than the hash of s3cr3t on server2: hashFunction('s3cr3t' + 'perUserSalt')
Use bcrypt, scrypt, or PBKDF2 only for password storage.

Should the Salt for a password Hash be "hashed" also?

This I think may be a silly question, but I have become quite confused on what I should do here for the best.
When salting a password hash, should the salt also be hashed or left as plaintext?
NOTE: I am hashing a password in SHA-256 and the Salt is a pre defined string as only one password will ever be stored at a time.
TIA
Chris (Shamballa).
It doesn't matter.
The purpose of a salt is to prevent pre-computation attacks.
Either way, hashing the salt or using it by itself, results in the same data being added as a salt each time. If you hash the salt, all you are effectively doing is changing the salt. By hashing it first, you convert it into a different string, which is then used as the salt. There is no reason to do this, but it will not do anything wrong if you do.
You just need to be consistent and use the same method every time or you will end up with a different password hash.
You must not hash the salt, since hashes are one way. You need the salt so that you can add it to the password before hashing. You could encrypt it, but it's not necessary.
The critical thing about salts is that each password should have its own salt. Ideally, each salt should be unique, but random is good too. The salt should therefore be long enough to allow it to be unique for each password.
If all salts are the same, it's obvious to the cracker (who can see your hash values), which accounts have the same password. The hash values will be the same. This means that if they crack one password, they get more than one account with no additional work. The cracker might even target those accounts.
You should assume that the cracker will gain both the salt and the hash value, so the hash algorithm must be secure.
Having any salt at all prevents using existing precomputed rainbow tables to crack your hash value, and having a unique salt for each account removes the desire for your cracker to precompute their own rainbow tables using your salt.
The salt should not be hashed, as you need the original value to combine with the password before hashing it.
No you must not hash the salt. The salt is in clear text and it is needed to you to recompute the password and check it with the one stored in the hashed password file.
But if you need a strong salting procedure you can compute your salted password in this manner:
SaltedHashedPwd = H(H(H(H(.....H(PWD-k+SALT-k)+SALT-k)+SALT-k).....)+SALT-k+N
H is the hash function
SALT-k is a k-random string you use as salt
PWD-k is the k-password
(every Password has a different salt)
N is the iterations number you compose the H function
In the PKCS#5 standard it uses N=1000!
In this manne a Dictionary attack is not possible because for every word into the Dictionary and for every SALT into the password file, the attacker needs to compute the Hash. Too expansive in time!
I think that N=100 should be enough for your uses :-)
As the salt needs to be saved along with the hash (or at least must be retrievable along with the hash), an attacker could possibly get both the salt and the hashed password. In some of my applications, I've stored the salt encrypted in the database (with a key known only to the application). My reasoning was that storing the salt unencrypted along with the hashed password would make it easier to crack the passwords, as a hacker that would be able to retrieve the password table (and would know or make an assumption about the hash algorithm) would be able to find matches between hashes of well known words (dictionary attack) by hashing each word in the dictionary and then salting with the salt he also has access to. If the salt would be encrypted, such an attack wouldn't be possible unless he would also have access to the encryption key known to the application.
(If anybody sees a fault in this logic, please comment.)

Difference between Hashing a Password and Encrypting it

The current top-voted to this question states:
Another one that's not so much a security issue, although it is security-related, is complete and abject failure to grok the difference between hashing a password and encrypting it. Most commonly found in code where the programmer is trying to provide unsafe "Remind me of my password" functionality.
What exactly is this difference? I was always under the impression that hashing was a form of encryption. What is the unsafe functionality the poster is referring to?
Hashing is a one way function (well, a mapping). It's irreversible, you apply the secure hash algorithm and you cannot get the original string back. The most you can do is to generate what's called "a collision", that is, finding a different string that provides the same hash. Cryptographically secure hash algorithms are designed to prevent the occurrence of collisions. You can attack a secure hash by the use of a rainbow table, which you can counteract by applying a salt to the hash before storing it.
Encrypting is a proper (two way) function. It's reversible, you can decrypt the mangled string to get original string if you have the key.
The unsafe functionality it's referring to is that if you encrypt the passwords, your application has the key stored somewhere and an attacker who gets access to your database (and/or code) can get the original passwords by getting both the key and the encrypted text, whereas with a hash it's impossible.
People usually say that if a cracker owns your database or your code he doesn't need a password, thus the difference is moot. This is naïve, because you still have the duty to protect your users' passwords, mainly because most of them do use the same password over and over again, exposing them to a greater risk by leaking their passwords.
Hashing is a one-way function, meaning that once you hash a password it is very difficult to get the original password back from the hash. Encryption is a two-way function, where it's much easier to get the original text back from the encrypted text.
Plain hashing is easily defeated using a dictionary attack, where an attacker just pre-hashes every word in a dictionary (or every combination of characters up to a certain length), then uses this new dictionary to look up hashed passwords. Using a unique random salt for each hashed password stored makes it much more difficult for an attacker to use this method. They would basically need to create a new unique dictionary for every salt value that you use, slowing down their attack terribly.
It's unsafe to store passwords using an encryption algorithm because if it's easier for the user or the administrator to get the original password back from the encrypted text, it's also easier for an attacker to do the same.
As shown in the above image, if the password is encrypted it is always a hidden secret where someone can extract the plain text password. However when password is hashed, you are relaxed as there is hardly any method of recovering the password from the hash value.
Extracted from Encrypted vs Hashed Passwords - Which is better?
Is encryption good?
Plain text passwords can be encrypted using symmetric encryption algorithms like DES, AES or with any other algorithms and be stored inside the database. At the authentication (confirming the identity with user name and password), application will decrypt the encrypted password stored in database and compare with user provided password for equality. In this type of an password handling approach, even if someone get access to database tables the passwords will not be simply reusable. However there is a bad news in this approach as well. If somehow someone obtain the cryptographic algorithm along with the key used by your application, he/she will be able to view all the user passwords stored in your database by decryption. "This is the best option I got", a software developer may scream, but is there a better way?
Cryptographic hash function (one-way-only)
Yes there is, may be you have missed the point here. Did you notice that there is no requirement to decrypt and compare? If there is one-way-only conversion approach where the password can be converted into some converted-word, but the reverse operation (generation of password from converted-word) is impossible. Now even if someone gets access to the database, there is no way that the passwords be reproduced or extracted using the converted-words. In this approach, there will be hardly anyway that some could know your users' top secret passwords; and this will protect the users using the same password across multiple applications. What algorithms can be used for this approach?
I've always thought that Encryption can be converted both ways, in a way that the end value can bring you to original value and with Hashing you'll not be able to revert from the end result to the original value.
Hashing algorithms are usually cryptographic in nature, but the principal difference is that encryption is reversible through decryption, and hashing is not.
An encryption function typically takes input and produces encrypted output that is the same, or slightly larger size.
A hashing function takes input and produces a typically smaller output, typically of a fixed size as well.
While it isn't possible to take a hashed result and "dehash" it to get back the original input, you can typically brute-force your way to something that produces the same hash.
In other words, if a authentication scheme takes a password, hashes it, and compares it to a hashed version of the requires password, it might not be required that you actually know the original password, only its hash, and you can brute-force your way to something that will match, even if it's a different password.
Hashing functions are typically created to minimize the chance of collisions and make it hard to just calculate something that will produce the same hash as something else.
Hashing:
It is a one-way algorithm and once hashed can not rollback and this is its sweet point against encryption.
Encryption
If we perform encryption, there will a key to do this. If this key will be leaked all of your passwords could be decrypted easily.
On the other hand, even if your database will be hacked or your server admin took data from DB and you used hashed passwords, the hacker will not able to break these hashed passwords. This would actually practically impossible if we use hashing with proper salt and additional security with PBKDF2.
If you want to take a look at how should you write your hash functions, you can visit here.
There are many algorithms to perform hashing.
MD5 - Uses the Message Digest Algorithm 5 (MD5) hash function. The output hash is 128 bits in length. The MD5 algorithm was designed by Ron Rivest in the early 1990s and is not a preferred option today.
SHA1 - Uses Security Hash Algorithm (SHA1) hash published in 1995. The output hash is 160 bits in length. Although most widely used, this is not a preferred option today.
HMACSHA256, HMACSHA384, HMACSHA512 - Use the functions SHA-256, SHA-384, and SHA-512 of the SHA-2 family. SHA-2 was published in 2001. The output hash lengths are 256, 384, and 512 bits, respectively,as the hash functions’ names indicate.
Ideally you should do both.
First Hash the pass password for the one way security. Use a salt for extra security.
Then encrypt the hash to defend against dictionary attacks if your database of password hashes is compromised.
As correct as the other answers may be, in the context that the quote was in, hashing is a tool that may be used in securing information, encryption is a process that takes information and makes it very difficult for unauthorized people to read/use.
Here's one reason you may want to use one over the other - password retrieval.
If you only store a hash of a user's password, you can't offer a 'forgotten password' feature.

Resources