Keys, and keys that protect people
🎯You'll be able to
Use surrogate and natural keys, and build pseudonymous keys with a secret salt so records about one person can be linked without exposing who they are.
🏠The everyday picture
An exam hall gives each student a roll number. Examiners mark papers by roll number and never see the names, but the office can still match results to students.
📘What it really is
-
A natural key comes from the source (
customer_id133,SKU-115). A surrogate key is made by the warehouse, often a number or a hash, so the model doesn't depend on a source's ids. -
A pseudonymous key replaces an identifier with a value that can't be traced back without a secret. Analysts can count customers and follow their orders, but can't see who they are.
-
Hashing alone isn't enough:
md5(phone)can be reversed by hashing every possible phone number (there are only about a billion 10-digit numbers) and looking up the result. The same goes for ids 1 to 600. -
Add a secret salt:
sha256(salt || customer_id). Without the salt, guessing doesn't work. SabziSathi'scustomer_keymacro reads the salt from theSABZI_KEY_SALTenvironment variable, so it's never stored in the project files. Keep the salt in a secret store, and keep it stable: a new salt makes new keys. -
Pseudonymised is still personal data under laws such as the DPDP Act and GDPR, because the company holding the salt can re-identify people. It reduces risk; it doesn't remove duties.
-
Reduce other details too:
signup_monthinstead of the exact date; area instead of address.
📝A worked example
Input: compare the starter's and the solution's dim_customers keys for customer 1.
Expected output: the starter's key is md5('+91 00000 00001'), which anyone can recompute from the phone number, and the table also holds
the name, phone and email. The solution's key is a 64-character SHA-256 value that only matches with the salt, and the table holds just
the key, signup_month and current_area. Project 2 test 4 tries unsalted MD5 and SHA-256 of ids, phones and emails, and checks none
match.
🌍Where it's used
- Healthcare research: patient keys that let studies follow a patient without names.
- Advertising and analytics: hashed identifiers, with salts, to limit what can be linked.
- Fintech: analysts work with customer keys; only support staff see names.
📝Case scenario
A transport department published "anonymised" journey data with card numbers replaced by unsalted hashes. Researchers hashed every possible card number in a day and re-identified millions of journeys. A secret salt, kept out of the release, would have prevented the reversal.
🖱️Try it
In Python, compute hashlib.md5(b'+91 00000 00001').hexdigest() and find it in the starter's dim_customers. Success: you have
"re-identified" customer 1 from their phone number, which shows why the starter's key isn't anonymous.
⚠️Common mistakes
- Unsalted hashes of identifiers. Sign: anyone can recompute them. Fix: a secret salt, kept outside the project.
- The salt in the code. Sign: the salt is in Git history. Fix: an environment variable from a secret store.
- Calling pseudonymised data anonymous. Sign: it's shared as if no rules apply. Fix: treat it as personal data with less risk.
🛠️For your project
Project 2 test 4 checks salted keys, and that the test's salt isn't stored in any warehouse file.
✅Quick check
Why isn't md5(phone) anonymous?
Show the answer
Anyone can hash every possible phone number and match the results.
Where should the salt live?
Show the answer
In a secret store, passed in as an environment variable, not in the project files.
