Elevate Your Security: The Power of Password Hashing and Salting
Tags: security, development, programming, algorithms
Published: 2024-02-01 01:04:19

Passwords are the primary defense we employ to protect our accounts and sensitive data. However, for so many mundane reasons we tend to use simple passwords against the advice of cybersecurity experts. This is one of many reasons I decided to write on this topic. The other reason would be probably because as a developer geared to make customer-centered applications, I'm concerned about the safety of their data. As much as I don't have control over what they choose to use as their passwords I could try to strengthen their choices, maybe. 
Your guess is as good as mine that cyber-attacks are rampant as days progress. some prevalent password attacks include;

1. Brute force attacks - Malicious actors in this context attempt all possible password combinations until they get the correct one to break into your account

1. Dictionary attacks - using a pre-compiled lists encompassing commonly used passwords/phrases or number combinations to crack passwords

1. Credential stuffing  - using stolen credentials to try to login into other accounts with hopes of reusing passwords

1. Phishing attacks - Deceiving unaware individual through deceptive websites or emails to reveal their passcodes or click malicious links by acting as trustworthy entities

1. Keylogger attacks - capturing passwords as users type them using malicious software that records the unique keystroke

1. Man-in-the-middle attacks - intercepting communications and altering the message/eavesdropping between the communicating parties

1. Rainbow table attacks - Attackers can quickly find the original password from a hash by using precomputed databases containing hashed values of frequently used passwords.

In the vast landscape of cyberspace, where data is both a commodity and a vulnerability, the importance of securing user passwords cannot be overstated. As software developers, we are not just creators of digital experiences; we are the gatekeepers of user trust. 

This blog takes you on a thorough exploration of the domains of salting and hashing passwords, illuminating their nuances, their function in bolstering digital security, and how knowing them can empower every line of code.

![hash-flow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v347hx2e4hknjcnjxt9h.png)
## Understanding Password Hashing: A Cryptographic Symphony
It would be a disservice to talk about hashing without a mention of cryptography. In layman's language cryptography is using mathematical algorithms to secure communications and information in transit by transforming its plaintext to ciphertext. 
So let's assume you signed up for this new website. You choose "Ndenoh@12345" as your new password. But it transforms before reaching the database to make it more secure. This is known as hashing.
Hashing is the cryptographic process that takes an input (in this case, your password) and transforms it into a fixed-size string of characters. This process is designed to be one-way, meaning it should be nearly impossible to reverse and obtain the original password.
Taking our "Ndenoh@12345" as an example and hashing using an algorithm like SHA-256 we could get something like 

```arduino
3f251adfba18404b4fe7b0f228d0408e0e85f32a2f1968472cda64367
```
Understand that hashing is like introducing a unique fingerprint for the password. This means even the tiniest change in the input will give a very different hash. This irreversibility is a crucial aspect of password hashing. So how would changing one letter affect the hash?
Let's consider the following sentences and their hash functions:
**First example**
```arduino
"The quick brown fox jumps over the lazy dog."
```
Hash (SHA-256):
```
c07548ac1d6b3543e9761da0c1b134ee5f0e0ef8c38c2c266da3caee7eb4c9b0
```
**Second example**
```arduino
"The quick brown fox jump over the lazy dog."
```
Hash (SHA-256):

```arduino
dfdbbfb09c38efdf58b8d593ab1e5b02c1f43ac48e813d97fe5206a46d78a1d8
```
Notice a change in the hash function? This is because we changed jumps to jump in the second sentence

## Hash collision
A hash collision is when two different keys generate the same index and key value. Collisions can happen if there are more keys to hash than there are value slots available in a database. To resolve hash collisions, methods known as collision resolutions are used, with the most common methods being open addressing (closed hashing) and separate chaining (open hashing). 
In open addressing, all keys and values are stored directly in the same hash table, so there remains an equal number of keys and value slots and no overlapping occurs. To accomplish this, linear probing, quadratic probing, or double hashing is used. With linear and quadratic probing, slots in a hash table are “probed” or looked through until an empty slot is found to store the colliding key value. With double hashing, two hash functions are applied, where the second function offsets and moves the colliding key value until an empty slot is found.


![salting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nhr7lcvqvkyf5ow2xrpu.png)
## Salting: An extra layer of protection

While hashing provides a robust layer of security, there are still vulnerabilities. Enter salting – an additional measure that enhances the security of hashed passwords.
Salting involves adding a unique random string (the salt) to each password before hashing. This means that even if two users have the same password, their hashed values will be entirely different due to the unique salts.

**Random salt example**
Let's generate a random salt: "L#k8sN!2". This will be combined with the password before hashing. If we take our previous password "Ndenoh@12345" and add the salt "L#k8sN!2" before hashing, the result might be: 

```arduino
5a9a4c3db1b1e8913038761d2f31d41857cf9c6a6c5367914609d36e1aa31a1a
```

**Understanding salting**
The salted hash is a combination of the hashed password and the unique salt. This adds a layer of complexity, rendering precomputed tables (rainbow tables) ineffective in cracking passwords.
What to avoid
While salting enhances security, it's essential to be aware of potential pitfalls. Forgetting to generate unique salts for each user or storing salts in the same database can compromise the effectiveness of salting. Best practices include using a cryptographically secure random number generator to create salts and storing them separately from the hashed passwords.

## Hashing Algorithms: Choosing the right weapon

The choice of the hashing algorithm is critical. Not all algorithms are created equal, and the landscape is ever-evolving. Let's delve into the world of hashing algorithms.
Common Hashing Algorithms:

1. MD5: Once popular, now considered weak due to vulnerabilities.

1. SHA-1: Also phased out due to vulnerabilities.

1. SHA-256 and SHA-3: Current industry standards, providing robust security.

**Implementation in code**
Let's take a look at a simplified Python example using the hashlib library

```python
import hashlib

def calculate_hash(input_text):
    # Create a new SHA-256 hash object
    sha256_hash = hashlib.sha256()

    # Update the hash object with the input text
    sha256_hash.update(input_text.encode())

    # Return the hexadecimal representation of the hash
    return sha256_hash.hexdigest()

# Original Sentence
original_sentence = "The quick brown fox jumps over the lazy dog."

# Modified Sentence (Changed one letter)
modified_sentence = "The quick brown fox jumps over the lazy bog."

# Calculate hashes
original_hash = calculate_hash(original_sentence)
modified_hash = calculate_hash(modified_sentence)

# Print the results
print(f"Original Sentence: {original_sentence}")
print(f"Hash (Original): {original_hash}\n")

print(f"Modified Sentence: {modified_sentence}")
print(f"Hash (Modified): {modified_hash}")
```
The results;

![hash results](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hh13e0re6vhehrus5js5.png)
This example highlights the straightforward implementation of hashing and salting using a SHA-256 algorithm and a secure method for generating salts.

## Best Practices: Crafting a Shield of Security
**Generate strong passwords**
Encourage users to create strong passwords containing a mix of uppercase and lowercase letters, numbers, and special characters.
**Use Cryptographically secure randomness**
Ensure that random numbers and salts are generated using cryptographically secure methods to prevent predictability.
**Regularly update hashing algorithms**
Stay abreast of industry standards and update hashing algorithms accordingly to protect against evolving threats.    **Store salts securely**
Keep salts separate from hashed passwords and ensure they are stored securely to maintain the integrity of the salting process.

![salt-hash workflow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xjkyilh80eloethj8vy8.png)
Salt-hashing workflow

- Step 1: User registration or password update - A user creates or updates their password, e.g., "SecurePassword123."

- Step 2: Generate a random salt e.g., "L#k8sN!2."

- Step 3: Combine password and salt - Concatenating the password and the salt, creating the input for the hash function. e.g., "SecurePassword123L#k8sN!2"

- Step 4: Hash the combined input Utilize a secure hash algorithm (e.g., SHA-256) to hash the combined input. Hashed value: 

```arduino
5a9a4c3db1b1e8913038761d2f31d41857cf9c6a6c5367914609d36e1aa31a1a
```

- Step 5: Store salt and hashed password. Store both the salt and the hashed password in the database. This ensures that the salt is available during future login attempts.

- Step 6: Authentication (During Login). The user provides their password during login.

- Step 7: Retrieve Salt from Database. Retrieve the corresponding salt associated with the user's account from the database.

- Step 8: Combine Password and Retrieved Salt - Concatenate the entered password and the retrieved salt. Combined input example would be "EnteredPassword123L#k8sN!2"

- Step 9: Hash the Combined Input - Use the same hash algorithm to hash the combined input. Our hash value is

```arduino
5a9a4c3db1b1e8913038761d2f31d41857cf9c6a6c5367914609d36e1aa31a1a
```

- Step 10: Compare Hashes - Compare the computed hash during login with the stored hashed password in the database.

- Step 11: Authentication Decision - If the hashes match, the entered password is correct, and the user is granted access.

## Conclusion: The Guardians of Digital Trust

In conclusion, password hashing and salting are the unsung heroes of digital security. Understanding their nuances is not just a technical necessity; it's a commitment to safeguarding user trust. The symphony of hashing and salting, fortified by robust algorithms and best practices, creates a harmonious melody of security. As developers, we are the guardians of digital trust, and every line of code becomes a pledge to uphold the sanctity of user data. Mastering the art of secure passwords is not just a skill; it's a responsibility that defines the future of digital landscapes.