In this lesson, you will learn how to implement salt-based hashing to protect sensitive identifiers like PII, ensuring that even if your database is compromised, individual records cannot be easily deanonymized via pre-computed attacks.
Why Hashing Isn't Enough
When dealing with identifiers (such as national ID numbers or email addresses), a simple hash like SHA-256 is insufficient. Attackers use "rainbow tables"—pre-computed databases of hashes for every common input—to reverse your identifiers instantly. To mitigate this, we use a salt: a unique, random string appended to the identifier before hashing.
Implementing Salted Hashing
The goal is to store a unique salt for each row, then hash the combination of the salt and the sensitive_identifier. This forces the attacker to compute a new rainbow table for every single row in your database, which is computationally infeasible.
Consider this table structure:
-- Storing the salt alongside the hashed identifier
CREATE TABLE user_identities (
user_id UUID PRIMARY KEY,
salt CHAR(32),
hashed_pii CHAR(64)
);
When an application receives an identifier, it performs the following steps:
- Retrieve or Generate: Fetch the
saltfor the user. If creating a new record, generate a cryptographically secure random string. - Concatenate:
combined_string = salt + sensitive_identifier. - Hash:
final_hash = SHA256(combined_string). - Store: Save the
saltand thefinal_hashin the database.
The Trade-off
Hashing is a one-way function. By hashing a sensitive identifier, you effectively lose the ability to perform range scans (e.g., "find all users born in 1990") or pattern matches (e.g., "find all emails ending in @company.com") on that specific field. You can only perform exact match lookups by applying the same salt and hashing process to the input provided by the user at runtime.
If your application requires the ability to reconstruct the original identifier, you should refer back to your knowledge of field-level encryption rather than hashing. Use hashing specifically when you need to verify an identity without ever exposing the raw, underlying data.
Key Takeaway: Always pair your hashing strategy with a unique, row-level salt to defeat rainbow table attacks and ensure your sensitive identifiers remain computationally resistant to reverse engineering.