Tuesday, 31 October 2023

How to store the password securely in a database?

Storing passwords or any sensitive information securely is a critical aspect in any application. In this post, I am going to talk about various approaches to store the passwords, and the pros and cons in each approach.

Hash the passwords

Use one-way hash algorithms to convert the given password into a fixed length of string.

 

Collision resistance

One way hash algorithms are designed in such a way that it is very difficult to find two different inputs that produce the same hash value.

 

What are the popular one-way hash algorithms?

some popular one-way hash algorithms include:

 

a.   SHA-2 (Secure Hash Algorithm 2)

b.   MD5 (Message Digest 5)

c.    RIPEMD-160 (RACE Integrity Primitives Evaluation Message Digest)

d.   BLAKE2

 

Following snippet generate a hash using SHA-256 algorithm

MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(string.getBytes());

Find the complete working application below.

 

HashGenerationDemo.java

package com.sample.app;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class HashGenerationDemo {
	public static String generateSHA2Hash(String string) throws NoSuchAlgorithmException {
		MessageDigest digest = MessageDigest.getInstance("SHA-256");
		byte[] hash = digest.digest(string.getBytes());
		return toHexString(hash);
	}

	private static String toHexString(byte[] hash) {
		StringBuilder hexString = new StringBuilder();
		for (byte b : hash) {
			hexString.append(String.format("%02x", b));
		}
		return hexString.toString();
	}

	public static void main(String[] args) throws NoSuchAlgorithmException {
		String message = "This is message is very sensitive and should be transferred securily";
		String hash = generateSHA2Hash(message);

		System.out.printf("Original message : %s\n", message);
		System.out.printf("Hash : %s", hash);

	}
}

Output

Original message : This is message is very sensitive and should be transferred securily
Hash : 129a200ca934a67d74d68ba04977151f3c2ad5cfac1f92d4a5675ba93a6855ad

Drawback of this approach

Rainbow table attacks: Attacker can create pre-computed tables of hash values for common passwords, and can then use this dictionary to generate collisions, which can be used to crack other passwords.

How to address this problem?

We can solve this problem by salting the password.

 

Salting the password

Salting the password makes the attacker task much more difficult to crack passwords using rainbow table attacks and collision attacks.

 


In this procedure, you generate a random text/value and add it to the actual password before hashing it.

 

hashedValue = hash(password+random_value)

 

Scenario 1: User 'A' register with username and password

When a person 'A' registers your website with the username and password. You are going to generate a random text/value, add it to the password and compute the hash. Your table looks like below.

 

id

username

salt

hased_password










                                            

Scenario 2: What if two different users registered with same password.

As the salt value generated for the two users is different, our application generates two different hashed passwords. You can confirm the same from below application.

 

HashGenerationUsingSalt.java

package com.sample.app;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class HashGenerationUsingSalt {

	public static String generateSalt() {
		SecureRandom random = new SecureRandom();
		byte[] salt = new

		byte[32];
		random.nextBytes(salt);
		return new String(salt, StandardCharsets.UTF_8);
	}

	public static String generateSHA2Hash(final String password) throws NoSuchAlgorithmException {
		String salt = generateSalt();
		String saltedPassword = password + salt;
		MessageDigest digest = MessageDigest.getInstance("SHA-256");
		byte[] hash = digest.digest(saltedPassword.getBytes());
		return toHexString(hash);
	}

	private static String toHexString(byte[] hash) {
		StringBuilder hexString = new StringBuilder();
		for (byte b : hash) {
			hexString.append(String.format("%02x", b));
		}
		return hexString.toString();
	}

	public static void main(String[] args) throws NoSuchAlgorithmException {
		String password = "password@334GT123";

		int count = 10;
		System.out.printf("Experiment by generating hash for the same password %d times\n", count);

		for (int i = 0; i < count; i++) {
			String hash = generateSHA2Hash(password);
			System.out.printf("%d. Generated hash : %s\n", i, hash);
		}

	}
}

Output

Experiment by generating hash for the same password 10 times
0. Generated hash : d0e9e10d549df962f06b6c810612a3639bff3949639a370dcf1a8ecc68f1c1d8
1. Generated hash : 7dfdb5815ba7c06258f9added188cc1ab918eeab9c2cf511ca9a86720042ce96
2. Generated hash : a9c3151cf5885c16f0e127cf0e444275a3e486fce47767b08ca11eb2733de69c
3. Generated hash : 02f9dbebde4e20fcd5b9b283ba51fcdc60e242a087c72475a8f24d5d7ae301d5
4. Generated hash : 3780aebc82a37eecb321875e8480f4a98717ccad8a203118780e6bbe4b381a4b
5. Generated hash : 6a1fbc126321b0ac14f2074f13b5b83dc43c72b08acf04872896c91c3ced6b75
6. Generated hash : 0d44d7e2add6c7233de8f735f6374c46bf1827db0f6c6c59f356fb1333fc15e0
7. Generated hash : 3deeaac8f2ab8297333458592eb9ca02c40e9a6fda4289dcf349e523bff96f7b
8. Generated hash : 52588d3fd5ea7c319faa7fdf98ac7ec4e2a04b5bf4ae78e802d0a0788a389a9a
9. Generated hash : a6f2c3d22b6b40ae006496d23fc6a3d1608c51cc5ac35cf97f7da88e3325cef2

References

Digital Signature

How to generate SHA-1 hash of a file?



                                                             System Design Questions

No comments:

Post a Comment