Improving password hashing for added security

Aseem Garg
Internshala Tech
Published in
5 min readSep 13, 2019

Co-writers: Amar Kumar & Sumit Chahal.

Keeping personal information safe and protected from hackers is always a priority for any businesses. Passwords play an important role in this; they often serve as the first line of defence in preventing unauthorized access to organizational resources and confidential data. There has been a lot of research and development with regard to securing passwords. One of the ways to do this is by hashing the passwords using different algorithms (MD5, SHA1, SHA256, PBKDF2, Bcrypt, Scrypt, Argon2). Before we proceed further, let’s understand what hashing is.

Hashing

Hashing is generating a value from a string of text using a mathematical function leading to a complex and unreadable string. A hash function is where a computer takes an input of any length (e.g. letters, numbers and symbols) and uses a mathematical formula to chop it, mix it up, and produce an output of a fixed length.

Hashing the string ‘123456’ using SHA-1 algorithm

Important points regarding Hashing

  • Hash function are one way i.e we cannot reverse the hash value
  • Hash function is many-to-one and thus implies collisions (different inputs can lead to same output)
  • Hash function always generates the same output for the same input

Because of these properties, hash functions are often used for verifying data integrity (for example, ensuring that a file isn’t corrupted after transfer over an unreliable network). However, because of the very same properties, raw hash functions are not the best choice for secure password storage, as demonstrated using the example below. Let’s assume we have the following passwords store in database -

In the above table aseem and amar have the same password 123456 and after hashing, both of them get the same hash value. If somehow, amar gets access to the database and he observes that aseem’s hashed password is same as his, he will be able to login to the system using aseem’s credentials (aseem’s username and amar’s password).

The problem

Earlier, we were using SHA1 as our hashing algorithm for our passwords. SHA-1 is very basic and weak as compared to other hashing algorithms. The major problem with this is that in case of password leak (such as this), these password hashes become available in the market along with the usernames. If a hacker figures out the hashing algorithm we are using, the hacker can then brute force passwords for a particular users. This is compounded by the fact that SHA1 is computationally inexpensive (it takes very less time and computational resource to generate a SHA-1 hash of a string) and therefore the brute force speed can be very high.

In order to enhance the security of our passwords, we decided to upgrade our hashing algorithm. To be more specific, we wanted an algorithm that would make it very difficult for hackers to brute force our passwords, even if the passwords were leaked somehow.

Enter Argon2.

Argon2

Argon2 is a key derivation function that was selected as the winner of the Password Hashing Competition in July 2015. It provides security against brute force attacks using a predefined memory size, CPU time, and a degree of parallelism to prevent GPU attacks. It also produces different outputs for the same input on each function call using a randomly generated string called ‘salt’ before hashing the password. This makes it impossible to tell if two passwords are the same without actually computing and comparing the hash with that salt, which is unique for every generated hash and is stored with the hash.

Computing the hash from the password takes certain time, memory and number of CPU threads. This information is then stored in the hash. These can be provided as inputs to the algorithm. The Argon2 algorithm accepts three parameters -

  • Time: Defines the execution time, given in number of iterations
  • Memory: Defines the memory usage, given in kilobytes
  • Parallelism Degree: Defines the number of parallel threads

If a process takes more memory, it would consume RAM of the server, while if it takes more CPU, it would run for longer, i.e increasing the “Memory” will eat up RAM, increasing “Parallelism Degree” will consume more CPU cores and increasing “Time” increases processing time. With Argon2, we can specify how much of each resource is to be utilized (time, memory and CPU cores) while computing the hash. This information is then stored in the hash itself.

For example, the following is the Argon2 hash of “hackme” and uses the following parameters: Time=12, Memory=512MB & Threads=16. We can see that are stored in the hash itself.

$argon2id$v=19$m=524288,t=12,p=16$UGhhQWxVVVJlWkhMd0JXUA$wsj35nfsbFf/6OoZOv3jjxRfKIx8iJ/ilNOVr3vEp4g

Now, each time we need to validate the password (generate hash from password), we need to consume 12 iterations, 512MB RAM and 16 cores of our system so that the same hash is generated and the password is validated. If we change these parameters in the hash, we will get different result and the hash won’t match. By ensuring that the resources required are sufficiently high, we can ensure that it takes unreasonably long for a brute force attacker to crack our passwords. This is because these resources would be required to try 1 password iteration and brute forcing would require millions of tries. Therefore, the resources and time required to try these millions of combinations would be very high and not feasible.

The next step is to figure out what are the ideal values for these parameters. We ideally want to keep the values sufficiently high so as to mitigate brute force attacks, but if we keep the values too high, during periods of high traffic our own servers may not have the resources to compute the hashes and users might start getting errors. Therefore, these values can be chosen depending on the expected load on the servers.

This is how we used Argon2 (Argon2id variant as it offers the best/hybrid resistance against side-channel attacks as well as GPU-based attacks) to improve the security of our passwords.

--

--