Blog | G5 Cyber Security

Using BCrypt Hashes as Database IDs

TL;DR

Storing BCrypt hashes directly in your database as primary keys can improve security by making ID guessing harder. However, it introduces complexities with indexing and retrieval. This guide explains how to do it safely and effectively.

1. Why Use a BCrypt Hash for IDs?

Traditional auto-incrementing integer IDs are predictable. An attacker knowing the range of your IDs can potentially guess valid records. Using a BCrypt hash (which is designed to be one-way) makes ID guessing significantly more difficult.

2. Generating the Hash

  1. Choose a Salt: A salt is random data added to the password before hashing. You’ll need to store this salt alongside the hash.
  2. Hash the Data: Use a strong BCrypt library in your chosen programming language. The input should be unique data associated with each record (e.g., timestamp, username, email). Do not use passwords!

Example using Python and the bcrypt library:

import bcrypt

data = "unique_record_identifier"
# Generate a salt
salt = bcrypt.gensalt()

# Hash the data with the salt
hash = bcrypt.hashpw(data.encode('utf-8'), salt)

print(f"Hash: {hash.decode('utf-8')}")

Store both the hash and salt in your database table.

3. Database Table Structure

Your database table should include at least these columns:

The id column should be set as your primary key.

4. Retrieving Data

  1. Hash the Input: When searching for a record, hash the same unique identifier you used to generate the original ID using the stored salt.
  2. Compare Hashes: Compare the generated hash with the hash stored in the database. If they match, you’ve found the record.

Example (Python):

import bcrypt

data_to_search = "unique_record_identifier"
hash_from_db = "your_stored_hash"
salt_from_db = "your_stored_salt".encode('utf-8')

# Hash the input data using the stored salt
hashed_data = bcrypt.hashpw(data_to_search.encode('utf-8'), salt_from_db)

# Compare the generated hash with the database hash
if hashed_data == hash_from_db:
    print("Record found!")
else:
    print("Record not found.")

5. Indexing Considerations

BCrypt hashes are long strings, making traditional indexing less effective. Consider these options:

Test performance carefully with realistic data volumes.

6. Security Best Practices

Exit mobile version