Hashing Algorithm
This article specifies the standardization and hashing rules required by California's DROP system. If you choose the pre-hashed ingestion path, you must implement these rules exactly. If you use the clear ingestion path, DataGrail handles this for you — but this reference is useful for understanding how matching works.
The hashing rules are defined by:
- California Delete Act (Civil Code section 1798.99.80 et seq.)
- CCR, title 11, section 7600 et seq.
- CalPrivacy DROP Technical Documentation (updated 2026)
General Process
For every identifier field:
- Standardize the value using the field-specific rules below
- Encode the standardized value as UTF-8
- Hash with SHA-256
- Encode the hash output as Base64
A DROP hash is always a 44-character Base64 string (typically ending with =).
Input → Standardize → UTF-8 bytes → SHA-256 → Base64 → 44-char string
Field Standardization Rules
Email
The following rules apply to email addresses before hashing:
| Rule | Example |
|---|---|
| Trim leading/trailing whitespace | " alice@co.com " → "alice@co.com" |
| Lowercase the entire address | "Alice@Co.COM" → "alice@co.com" |
| Do not remove dots, plus signs, or other characters | "a.lice+tag@co.com" stays as-is |
Phone
The following rules apply to phone numbers before hashing:
| Rule | Example |
|---|---|
| Strip all non-numeric characters | "+1(415)555-9317" → "14155559317" |
| Keep the last 10 digits (or all digits if fewer than 10) | "14155559317" → "4155559317" |
Test vectors:
| Input | Standardized | SHA-256 Base64 |
|---|---|---|
+1(415)555-9317 | 4155559317 | vGM7y5n+hBXRSEAklhHDPCbysyNgYTmXdMcagGUOY8E= |
+84(90)123 4567 | 4901234567 | ptzVkgbv9DonwvPCHmXmJ2SEOaolSh37z3ZzY/Gmm+U= |
Name (First Name, Last Name — hashed separately)
The following rules apply to first and last names before hashing:
| Rule | Example |
|---|---|
| Replace accented Latin characters with ASCII | "José" → "jose" |
| Transliterate Greek and Cyrillic to Latin | "Иван" → "ivan" |
| Do not transliterate CJK, Arabic, or Hebrew | Characters kept as-is |
| Compound first names → single unit (remove spaces) | "Juan Pablo" → "juanpablo" |
| Remove hyphens, apostrophes, spaces | "O'Brien" → "obrien" |
| Lowercase | "SMITH" → "smith" |
Test vectors:
| Input | Standardized | SHA-256 Base64 |
|---|---|---|
Juan Pablo | juanpablo | 91hIbrbzNeqHs3o81O5yNrXUj7wDd2shvZ6THKi9qz8= |
Martinez | martinez | 2wRPGbwBNxhShjRczx8GfS2c4cjvs4NJskeWloUNtp8= |
Date of Birth
The following rule applies to dates of birth before hashing:
| Rule | Example |
|---|---|
Format as YYYYMMDD | "July 4, 1776" → "17760704" |
Test vector:
| Input | Standardized | SHA-256 Base64 |
|---|---|---|
July 4, 1776 | 17760704 | skXYXxBER6HQTZ3rXSZH1wVGLQ054mS5rbR/bwvzy4I= |
ZIP / Postal Code
The following rules apply to ZIP and postal codes before hashing. Note that all four rules must be applied in order — the "Lowercase" example below shows an intermediate value before truncation.
| Rule | Example |
|---|---|
| Keep alphanumeric characters only | "91790-3771" → "917903771" |
| Lowercase | "M1B 1A1" → "m1b1a1" |
| Take first 5 characters | "917903771" → "91790" / "m1b1a1" → "m1b1a" |
| Remove leading zeros | "01234" → "1234" |
Test vectors:
| Input | Standardized | SHA-256 Base64 |
|---|---|---|
91790-3771 | 91790 | 2FPZucR4x7U8KlM+SFAX4LPGhwNz/PIZUCSUdDh0o/s= |
M1B 1A1 | m1b1a | n8L9q8mVeT6Xt9/EeUNiTukGDrkbPJ3DvOEx14uElxk= |
VIN (Vehicle Identification Number)
The following rules apply to VINs before hashing:
| Rule | Example |
|---|---|
| Keep alphanumeric characters only | Already alphanumeric |
| Lowercase | "1HGCM82633A004352" → "1hgcm82633a004352" |
| Must be exactly 17 characters after normalization | — |
MAID (Mobile Advertising ID)
The following rules apply to MAIDs before hashing:
| Rule | Example |
|---|---|
| Keep hex characters only (0-9, a-f) | Strip hyphens from GUID format |
| Lowercase | "A1B2C3D4..." → "a1b2c3d4..." |
| Must be exactly 32 characters after normalization | — |
CTVID (Connected TV ID)
The following rules apply to CTVIDs before hashing:
| Rule | Example |
|---|---|
| Keep alphanumeric characters only | — |
| Lowercase | — |
| Must be 8–32 characters after normalization | — |
Composite Hashing
DROP defines two composite list types that hash multiple fields together. The process is:
- Standardize and hash each component field separately (producing a Base64 string per field)
- Concatenate the Base64 strings in the specified order with no separator
- Encode the concatenated string as UTF-8
- Hash the concatenation with SHA-256
- Encode as Base64
field_1_hash = Base64(SHA256(standardize(field_1)))
field_2_hash = Base64(SHA256(standardize(field_2)))
composite = Base64(SHA256(field_1_hash + field_2_hash + ...))
NDZ: First Name + Last Name + DOB + ZIP
Concatenation order: hash(first) + hash(last) + hash(dob) + hash(zip)
Worked example: Danielle Johnson, born July 4, 1985, ZIP 91790
| Field | Standardized | SHA-256 Base64 |
|---|---|---|
| First Name | danielle | 5dUD1FgiKcTJq+JQ5JZUdlyIXrSbtJ338YYbt5/HNG4= |
| Last Name | johnson | K+TjOqPiH2/3rRRPj9WCKKHM47UDQLSAX/DGNIDuxIg= |
| DOB | 19850704 | IWi7qxOAbBJe0fNciDj76Eg84gmj40rB7aNMK/VnFOI= |
| ZIP | 91790 | 2FPZucR4x7U8KlM+SFAX4LPGhwNz/PIZUCSUdDh0o/s= |
Final NDZ hash: PQOfn1RffEKmqMmNAzDKKaoZCwxWbQZkQzPWmQo9REA=
NameVIN: First Name + Last Name + VIN
Concatenation order: hash(first) + hash(last) + hash(vin)
Worked example: Eve Genesis, VIN 1HGCM82633A004352
| Field | Standardized | SHA-256 Base64 |
|---|---|---|
| First Name | eve | hSYq33RRi7twx8uUzWFZ2RZp5age3x7+vVQ+rb2p+is= |
| Last Name | genesis | ruutSnlvzC4V3ExgYbRe2bNz8mrfx5jKfS2MxYGCcY4= |
| VIN | 1hgcm82633a004352 | iNswy1m+0VSt8jAfFrvaiQ1R/0HAbgSwNGkwqo6QBss= |
Final NameVIN hash: rtnDuXIe63jXYQQXW5r07GJ7lSsrib8+46QuKFwkOmk=
If a consumer has multiple VINs, generate one NameVIN hash per VIN (same name fields, different VIN each time).
DROP List Types Summary
The table below maps each DROP list type to its hash input and required fields:
| List Type | Hash Input | Required Fields |
|---|---|---|
| Single email address | emails[] | |
| Phone | Single phone number | phones[] |
| NDZ | First + Last + DOB + ZIP (composite) | name.first, name.last, dob, zip |
| NameVIN | First + Last + VIN (composite) | name.first, name.last, vins[] |
| MAID | Single Mobile Ad ID | maids[] |
| CTVID | Single Connected TV ID | ctvids[] |
Implementation Checklist
Before submitting your first ingestion, verify each of the following:
- Implement each field standardization rule exactly as specified
- Verify SHA-256 output using the test vectors above
- Verify Base64 encoding (standard Base64 with
=padding, not URL-safe) - For composites (NDZ, NameVIN): hash fields individually first, then concatenate the Base64 strings, then hash the concatenation
- For consumers with multiple values (e.g., 3 emails), produce one hash per value
- For consumers with multiple VINs, produce one NameVIN hash per VIN
- Validate your output against the reference implementation before submitting your first ingestion
Disclaimer: The information contained in this message does not constitute as legal advice. We would advise seeking professional counsel before acting on or interpreting any material.