Get a Pentest and security assessment of your IT network.

Cyber Security

bcrypt: Storing Salts Explained

TL;DR

Yes, you do need to store the salt generated for each password when using bcrypt. While the salt isn’t a secret like the password itself, it’s crucial for security and verifying logins.

Why Salts Matter with bcrypt

bcrypt is designed to be slow, making brute-force attacks harder. Salts add another layer of protection against precomputed rainbow table attacks. Here’s why you can’t skip storing them:

  • Rainbow Tables: These are precalculated tables of password hashes. Without a unique salt for each password, attackers could use these to quickly crack many passwords at once.
  • Unique Salts Prevent Reuse: If two users have the same password, but different salts, their bcrypt hashes will be completely different. This stops an attacker who cracks one user’s password from automatically cracking others.

How bcrypt Uses Salts

bcrypt doesn’t just hash the password; it combines (mixes) the password with a randomly generated salt before hashing. The resulting hash includes information about both the password and the salt.

Step-by-Step: Storing bcrypt Hashes Correctly

  1. Generate a Salt: When a user creates an account, generate a unique random salt for them. Most bcrypt libraries have functions to do this automatically.
    # Python example using bcrypt
    salt = bcrypt.gensalt()
  2. Hash the Password with the Salt: Use the bcrypt hashing function along with the generated salt to create the password hash.
    # Python example
    hash = bcrypt.hashpw(password.encode('utf-8'), salt)
    
  3. Store Both Hash and Salt: Store both the resulting hash and the original salt in your database. Do not derive the salt from the hash; store it separately.

    Your database table might look like this:

    • user_id (integer)
    • password_hash (string – the bcrypt hash)
    • salt (string – the unique salt used for that user)
  4. Verify Passwords During Login: When a user logs in:
    1. Retrieve the stored hash and salt from your database.
    2. Use the bcrypt verification function with the entered password and the retrieved salt.
      # Python example
      if bcrypt.checkpw(entered_password.encode('utf-8'), stored_hash.encode('utf-8')):
          # Password matches!
      else:
          # Incorrect password

Important Considerations

  • Salt Length: Use a sufficiently long salt (at least 128 bits / 16 bytes is recommended). The bcrypt library usually handles this for you.
  • Don’t Derive Salts: Never try to recreate the salt from the hash itself. This defeats the purpose of using salts in the first place!
  • Library Functions: Always use well-vetted bcrypt libraries (e.g., bcrypt for Python, bcryptjs for Node.js) instead of trying to implement it yourself. These libraries handle many security details correctly.
Related posts
Cyber Security

Zip Codes & PII: Are They Personal Data?

Cyber Security

Zero-Day Vulnerabilities: User Defence Guide

Cyber Security

Zero Knowledge Voting with Trusted Server

Cyber Security

ZeroNet: 51% Attack Risks & Mitigation