This recipe teaches us how to create a truly secure strong hash and how to strengthen it as computers becomes more capable of breaking it.
There are libraries that provide secure hash functionality, but we are going to use a standard, plain java algorithm named PBKDF2WithHmacSHA1
. So, we won't need any third-party libraries.
To create the first hash (Sign up), follow the given steps:
To generate a strong hash, please consider the code shown in the following screenshot:
We can test it by running the code shown in the following screenshot:
It should print the result as shown in the following screenshot:
For the getSalt
function, consider the code shown in the following screenshot:
Also, consider the following code for the toHex
and fromHex
functions:
This was pretty easy considering it's generating a really strong hash! Keep in mind that this code is just an example, for real development it should be coded in a maintainable way.
Now, we've just seen how to create the password hash. This is useful for creating a new user with a new password, or changing the old password for a new one, but how about authentication?
To compare hashes (Authentication), follow the given steps:
Consider the code shown in the following screenshot, which is used to validate a user:
As you can see, it returns a Boolean value: true
when the password is valid, false
when the password is invalid.
You probably noticed a new function here named slowEquals
. This function performs a length-constant time comparison in order to avoid timing attacks. It is a theoretical attack and I seriously doubt whether it could be done over the internet, but it's nice to be aware of the slowEquals
function.
Consider the following code that performs a length-constant time comparison:
That's it! We can now generate and validate passwords in a secure way; and even better, as technology evolves, we can increase the amount of iterations in order to make our hashes stronger!
We've seen that salting help us to make it harder to break our hashes, and it's impractical to use rainbow tables or dictionaries. However, salting does not protect against brute-force attacks since SHA algorithms are designed to be fast; as technology evolves, these hashes will be broken eventually. To make these attacks less effective, we can use a technique known as key stretching.
The idea is to make the hash function more long and complex. So, even with a fast CPU or custom hardware, dictionary and brute-force attacks are too slow to be worthwhile. The goal is to make the hash function slow enough to impede attacks, but still fast enough to not cause a noticeable delay for the user.
Key stretching is implemented using a special type of CPU-intensive hash function. Don't try to invent your own. Simply hashing the hash of the password iteratively isn't enough as it can be parallelized in hardware and executed as fast as a normal hash. Use a standard algorithm like PBKDF2 (the one we used), Bcrypt, or Scrypt. These are very strong and well-tested algorithms.
These algorithms take a work factor (also known as security factor) or iteration count as an argument. This value determines how slow the hash function will be. When computers become faster next year, we can increase the work factor.
It's important to remember that hashing is the last defense, and as such we should use the best protection available because if an intrusion happens, we will need it.
Also, if an intrusion does happen, there are several things we must do as responsible IT professionals:
3.16.135.36