A DROP deletion list is a CSV of two columns: a work item ID and a hash. There is no name in it, no email address, no phone number. To find out whether a request applies to one of your records, you standardize your own field the way DROP standardizes its own, hash it the same way, and compare the strings.
That is the entire matching mechanism, and it is unforgiving. A hash is a cliff, not a slope: standardize a value one character differently and you get a completely different 44-character string that will never match anything, and nothing in the output tells you it is wrong.
The digest: SHA-256, UTF-8 in, Base64 out
DROP's API description fixes three things at once: all hashes use SHA-256, the input encoding is UTF-8, and the output is Base64. Standard Base64, with + and /, not the URL-safe alphabet. A SHA-256 digest is 32 bytes, so every hash you produce is 44 characters and ends with a single = pad.
Three easy ways to get this wrong: emitting hex instead of Base64, emitting URL-safe Base64, or hashing the raw string bytes of some other encoding. All three produce a plausible-looking value.
Standardization, field by field
Standardization is where the real risk lives, because each field has its own rule and several of the rules are counterintuitive.
| Field | Rule | Result |
|---|---|---|
| Remove all whitespace, then lowercase. Do not remove dots, plus signs, or other characters. | a.b+tag@X.com becomes a.b+tag@x.com, dots and plus intact. | |
| DOB | Format as YYYYMMDD with no separators. | 1985-03-04 becomes 19850304. |
| Phone | Keep digits only, then retain the last 10 digits, or all digits if fewer than 10 remain. | +1 (415) 555-0142 becomes 4155550142. |
| ZIP | Keep alphanumeric characters only, drop the +4, lowercase, remove leading zeros, use the first five characters present. | 09021-4455 becomes 9021. |
| Name | Normalize Unicode, lowercase, transliterate supported Greek and Cyrillic, fold supported Latin to ASCII, then keep only letters and digits. | Sofía becomes sofia. |
| MAID | Keep only hexadecimal characters, lowercase. The standardized value must be 32 characters. | An uppercase UUID with dashes becomes 32 lowercase hex characters. |
| VIN | Keep only alphanumeric characters, then lowercase. Must be 17 characters. | 1HGCM82633A004352 becomes 1hgcm82633a004352. |
| CTVID | Keep only alphanumeric characters, then lowercase. Must be 8 to 32 characters. | CTV-7f3a91b2-XX becomes ctv7f3a91b2xx. |
Three rules that bite
- Email is not canonicalized. Most email libraries strip Gmail-style dots and
+tagsuffixes by default. DROP explicitly says not to. Using a library default here silently breaks every address that has a dot or a plus in it. - ZIP loses its leading zeros.
09021standardizes to9021, four characters. Every East Coast ZIP code goes through this transformation, and a ZIP stored as a number in a spreadsheet has often already lost the zero in a different way. - MAID and DOB fail loudly rather than guessing. A MAID that does not standardize to exactly 32 characters is an error, not a short hash. A date that does not read as
YYYYMMDDafter separators are dropped, such as03/04/1985, should be rejected rather than standardized into the wrong string.
One more honest caveat: the published rule says "supported Greek and Cyrillic characters" without enumerating them. Any implementation therefore picks a transliteration table, and a broker whose records carry Greek or Cyrillic names should treat those rows as unverified until the agency publishes the table. Latin-script names, the overwhelming majority, are unaffected.
Composite hashing: NDZ and NameVIN
Four of the six DROP list types are simple: Email, Phone, MAID and CTVID each hash one standardized field. Two are composites, and they are hashed twice.
For a composite, each field is standardized and hashed on its own first. Then the resulting Base64 hashes are concatenated in a required order, and that concatenated string is hashed again. The field orders are fixed:
- NDZ uses FirstName, then LastName, then DOB, then ZIP. Four field hashes, 4 times 44 = 176 characters concatenated, hashed once more.
- NameVIN uses FirstName, then LastName, then VIN. Three field hashes, 132 characters, hashed once more. DOB and ZIP take no part: NameVIN is not NDZ with a VIN bolted on.
First name and last name are standardized and hashed separately, never joined into one string. That is the first trap. The second is the order: it is fixed and it is not alphabetical. Swapping FirstName and LastName produces a perfectly well-formed 44-character hash that matches nothing.
A worked NDZ example
The values below are the hand-derived vectors pinned as regression tests in DropDue's matching engine. There is no official test vector for any of this: the DROP API document carries sample hashes but never publishes the plaintext behind them, so they cannot be reproduced. Every value here was derived from the published standardization rules and cross-checked against two independent SHA-256 implementations. You can re-derive any line with printf '%s' <standardized> | openssl dgst -sha256 -binary | base64.
Take one subject: first name Sofía, last name Méndez, date of birth 1985-03-04, ZIP 09021-4455.
- sofia
- hoRuhPm/sgU6SCMZOEPSKgviSnXTBNb4ouTS+sRF76o=
- mendez
- V9hHe2BpDtwiJfcNupxA/ehAyPJkx/R8PYDqWTqxHc0=
- 19850304
- 2GQAyBUbtv71YW4Aqz1QYk48EKvujagJpIGv2ix/+hw=
- 9021
- A286lqQ1yEvoEP5aQoxOn0XF7q0La/jdjIyzHVF0gpk=
- NDZ composite
- vbvLExSgChAMw5kF2F7bLFdMkZFfLno0GxIOIblqsmg=
The four labels on the left are the standardized values: the accents folded away, the date lost its separators, and the ZIP lost both its +4 and its leading zero. The composite on the last line is SHA-256 of those four Base64 strings concatenated in NDZ order, nothing else.
Why a subtly wrong hash is worse
Two near-miss implementations of that same subject are worth spelling out, because both look completely healthy from the outside.
| Mistake | Result | Matches? |
|---|---|---|
| LastName hashed before FirstName | p69FQDZlXJaWsbFEgJUelj4ipK2yo6nRn8wkioT/018= | Never. |
| Hashing the concatenated standardized values instead of the field hashes | 6SryZRJiFi+utV9bInswW/+QHQ9RwdoYUodhygEiGts= | Never. |
Both are well-formed Base64 SHA-256 values of exactly the right length. Both are produced without any error, exception or warning. And both simply never intersect the DROP list, which means every cycle they run comes back clean.
That is the failure mode that should worry a data broker most: not a crash, but a run of quiet cycles reporting zero matches while real deletion requests go unactioned. A crash gets fixed on the day it happens. A silent miss compounds for as long as nobody checks. If you want to check one field or one composite against a reference implementation, the hash checker shows the standardized string, every intermediate hash, and the final Base64 side by side.
Hash your records where they already are. DropDue's self-serve path hashes in the browser with WebCrypto, so raw identifiers never leave the machine they are on.
A short checklist before your first cycle
- Confirm your output is standard Base64 and 44 characters, not hex and not URL-safe.
- Confirm your email path preserves dots and plus signs.
- Confirm a ZIP with a leading zero and a +4 standardizes to four characters, not five or nine.
- Confirm your composites hash the field hashes, not the joined field values.
- Confirm the composite field order against the published order, and write a test that fails if it is swapped.
- Confirm a malformed MAID, VIN or DOB raises an error rather than producing a short hash.