Passwords are an essential part of our digital lives, and they play a crucial role in protecting our online identities and sensitive information. However, not all passwords are created equal, and the consequences of a compromised password can be severe. This is where password security comes in.

Logo

To keep passwords safe, one of the key components of password security is password hashing (which we discussed in my previous post). Password hashing is the process of converting a plain-text password into an unreadable string of characters, making it more difficult for attackers to access sensitive information.

In this blog post, we will explore the importance of password security and hashing, and why bcrypt is a future-proof solution for password security. We will also discuss the concept of salting and how it enhances the security of password hashing. Finally, we will provide a detailed explanation of how bcrypt works and why it is an excellent choice for protecting passwords against unauthorized access. So, let’s dive in!

The importance of password security

Picture this: you wake up one day and realize that someone has hacked into your email account. You panic as you think about all the sensitive information that’s stored in your inbox, like your banking information, personal photos, and private conversations. You feel violated and powerless, wondering how this could have happened. Unfortunately, this scenario is all too common.

In today’s digital world, we rely on passwords to protect our most valuable assets, from bank accounts to social media profiles. But the reality is that not all passwords are created equal, and a weak or compromised password can have devastating consequences.

Password security refers to the measures taken to protect passwords from unauthorized access. This includes creating strong passwords, storing them securely, and using additional security measures like two-factor authentication.

Password security is not just about creating strong passwords and storing them securely - it’s also about using strong hashing algorithms to protect passwords from attacks. A hashing algorithm is a mathematical function that takes a password as input and produces a fixed-length output, which is then stored in a database.

PasswordStoring Figure 1: How passwords are stored in application databases

The strength of a hashing algorithm is determined by how difficult it is to reverse engineer the output back to the original password. A weak hashing algorithm can be easily cracked using brute-force methods, where an attacker systematically tries different password combinations until they find a match.

By using a strong hashing algorithm like bcrypt, you can significantly reduce the risk of your passwords being compromised. Even if an attacker gains access to your password database, they will have a much harder time cracking the hashed passwords, which can buy you valuable time to respond and mitigate the damage.

How passwords are stored

When you create an account on a web application, your password is typically stored in a database on the application’s server. However, storing passwords in plain text is a major security risk, as it makes it easy for hackers to access the passwords if they are able to breach the server’s security. Instead, web applications use a process called hashing to convert the password into an irreversible, fixed-length string of characters.

PasswordsComparing Figure 2: Password validation

When a user enters their password to log in, the web application hashes the password using the same algorithm that was used to store the original password. The resulting hash is then compared to the hash that was stored in the database. If the two hashes match, the user is authenticated and granted access to their account. If the hashes don’t match, the user is denied access.

Salting

One important consideration when hashing passwords is the use of salting. A salt is a random string of characters that is added to the password before it is hashed. Salting adds an extra layer of security by making it much more difficult for hackers to use precomputed hash tables or rainbow tables to crack the passwords.

Instead, the hacker would need to generate a new hash table for each individual salt value, greatly increasing the amount of computational resources required to crack the passwords.

Salting Figure 3: Password validation with salt

Web applications typically store both the hashed password and the salt value in the database. When a user logs in, the salt value is retrieved from the database and used to hash the password entered by the user. This hash is then compared to the stored hash to determine if the user is authenticated.

With irreversible hashes and random salts, web apps can greatly reduce password-related security breaches. For hashing passwords, Bcrypt is a popular and highly effective algorithm. It’s used extensively in web applications and other systems to protect sensitive data.

Understanding bcrypt

Unlike some other hashing algorithms, such as SHA-256 or MD5, bcrypt is specifically designed for password hashing and includes additional security features that make it more difficult for hackers to crack passwords.

One of the key features of bcrypt is that it is deliberately slow (it has a built-in key-stretching function). This may sound counterintuitive - after all, we want password checking to be fast, right? - but in fact it’s an intentional design choice that helps to make bcrypt more secure.

The idea behind the slow hashing is to make it more difficult for hackers to crack the password using brute-force methods. Bcrypt slows down the hashing process, so it takes more computing power to hash each password, which means it takes an attacker longer to try all possible passwords.

Moreover, bcrypt also includes a built-in mechanism for salting. When a password is hashed with bcrypt, a unique salt value is generated for that password and included in the resulting hash. This makes it much more difficult for hackers to use precomputed hash tables or rainbow tables to crack the passwords.

Another feature of bcrypt is that it automatically generates a fixed-length output of 60 characters, regardless of the length of the input password. This helps to prevent attackers from identifying short or simple passwords by looking for patterns in the hashed output.

Finally, bcrypt includes a feature called “work factor” that allows developers to adjust the strength of the hashing algorithm based on the amount of computational resources available. A work factor measures how many times a password is hashed, and higher work factors require more CPU power.

How bcrypt works

The bcrypt is a password hashing function based on the Blowfish cipher. It takes in a password (up to 72 bytes long), a numeric cost (work factor) and a randomly generated salt value as inputs. The salt value is typically 16 bytes long and is generated using a secure random number generator. The salt value is then appended to the password, forming a single string that is used as input for the algorithm.

bcrypt Figure 4: bcrypt algorithm inputs

As a result, bcrypt generates a 60-character hash value. The whole hash value is a string of the form:

bcryptHash Figure 5: bcrypt hash string structure

For example, the hash value for the password hello with a work factor of 12 and algorithm version 2a would look like this:

$2a$12$o7GCRMgdcWBzliFHgiksCurofwc25X..eixme21sJugNGzPrkyOY.

Where:

  • The first two characters of the hash value indicate the algorithm version (e.g. 2a).
  • The next two characters indicate the work factor (in our example, 12).
  • The remaining 56 characters are the salt value and the hashed password.

Algorithm

The bcrypt algorithm runs this input string through a modified version of the Blowfish encryption algorithm. The bcrypt variant of Blowfish is slightly modified to include a key expansion function that is used to generate a set of subkeys from the password and salt inputs.

Then the algorithm uses this set of subkeys to encrypt a fixed block of data. The output of this encryption is then used as input for the next round of encryption, and the process is repeated a specified number of times (determined by the work factor parameter).

The number of rounds of encryption is determined by the work factor parameter, which specifies the logarithmic value of the number of rounds. For example, a work factor of 10 means that the password is hashed 2^10 (or 1,024) times. By increasing the work factor, the number of rounds of encryption can be increased, making it more difficult for attackers to crack the password.

The pseudocode for the bcrypt algorithm is shown below:

Input: Password, Salt
Output: Hashed Password

// Generate subkeys from password and salt
subkey[0...17] = P_orig[0...17]
for (i = 0; i < 18; i++) {
    subkey[i] = subkey[i] XOR S_orig[i % saltlen]
}
ciphertext = Encrypt(subkey, P_orig)

// Encrypt ciphertext multiple times
for (i = 1; i <= workfactor; i++) {
    subkey = ExpandKey(P_new)
    ciphertext = Encrypt(subkey, ciphertext)
}

// Concatenate salt and ciphertext and return result
hash = Concatenate(S_orig, ciphertext)
return hash

Where ExpandKey is the key expansion function, and Encrypt is the encryption function.

The algorithm first generates a set of subkeys from the password and salt inputs. This is done by XORing the first 18 bytes of the password with the salt value, and then using these bytes to encrypt a fixed block of data using the Blowfish encryption algorithm.

The resulting ciphertext is then encrypted multiple times (determined by the work factor parameter), with each round of encryption using the previous output as input. This process makes it difficult for attackers to reverse-engineer the hash value to obtain the original password.

Finally, the salt value is concatenated with the final ciphertext value to form the hashed password. The salt value is stored alongside the hashed password in the database, and is used to verify the password when the user logs in.

For more details on how bcrypt works, see the Hashing in Action: Understanding bcrypt or wikipedia article.

Bcrypt usage

One important feature of the bcrypt algorithm is the inclusion of the salt value in the hash output. The salt value is stored alongside the hash value in the database, and is used to verify the password when the user logs in.

bcryptUsage Figure 6: Bcrypt usage in application

When the user logs in, the salt value is retrieved from the database and combined with the input password to generate a new hash value. If the new hash value matches the stored hash value, the password is considered to be correct.

Bcrypt vs. other algorithms

There are several password hashing algorithms available, but not all of them are equally secure. Bcrypt is a popular choice for password hashing because it offers several advantages over other algorithms.

There’s a reason why Bcrypt is slow and computationally intensive. Hashing a password takes longer, so attackers have a harder time cracking it. Other algorithms like MD5 and SHA-1 are much faster, which makes them vulnerable to brute-force attacks.

Bcrypt allows you to adjust the “work factor” parameter, which controls how many times the password is encrypted during the hashing process. This makes it possible to increase the security of your password hashes over time as computers get faster and attackers get more sophisticated.

Whenever Bcrypt generates a hash, it automatically includes a salt value. Even if two users have the same password, their hashes will be different because each salt value is unique. Other algorithms require you to manually include a salt value, which can be forgotten or implemented incorrectly.

Moreover, bcrypt is widely supported by programming languages and frameworks, which makes it easy to use in your own applications. It’s also a proven algorithm that has been extensively studied and tested, so you can be confident in its security.

Choosing a hash function depends on its purpose, as I mentioned in this blog post). For data storage or data integrity, you should use a cryptographic hash function like SHA-256 or SHA-3. When it comes to password hashing, use bcrypt or PBKDF2.

Example usage in Python

The bcrypt library is available for Python 2.7 and 3.4+. It can be installed using pip: pip install bcrypt.

For example, we can hash a password, verify the password, and store the salt and hashed password in the database as follows:

import bcrypt

username = "kamil"

# Hash a password with a random salt
password = b"hello world"
salt = bcrypt.gensalt()

hashed_password = bcrypt.hashpw(password, salt)

# Store the salt and hashed password in the database
db.store_password(username, salt, hashed_password)

# Verify the password
entered_password = b"hello world"
stored_salt, stored_hashed_password = db.get_password(username)

hashed_entered_password = bcrypt.hashpw(entered_password, stored_salt)

# Compare the hashed entered password with the stored hashed password
if hashed_entered_password == stored_hashed_password:
    print("Password is correct!")
else:
    print("Password is incorrect.")

In this example, we first generate a random salt using the gensalt() function, and then use it to hash a password using the hashpw() function. We then store the salt and hashed password in the database.

Later, when a user logs in, we retrieve the stored salt and hashed password from the database. We then hash the entered password using the same salt value, and compare the resulting hash with the stored hash value to verify the password. If the hashes match, we know the password is correct.

Conclusion

In conclusion, password security is a critical aspect of protecting our online identities and sensitive information. Password hashing is an essential component of password security, and bcrypt is a future-proof solution for it.

Bcrypt is designed specifically for password hashing and includes additional security features that make it more challenging for attackers to crack passwords. By using bcrypt, web applications and other systems can effectively safeguard sensitive data, thereby reducing password-related security breaches.

Ultimately, ensuring password security requires a multifaceted approach, including creating strong passwords, storing them securely, and using additional security measures like two-factor authentication.

By the way, if you’re interested in learning more about password security, check out my blog post on the essentials of password hashing.