Addresses in the list are hashes, not addresses
The task. Suppress a client’s recipients on the node so that neither the node itself nor anyone who reaches its management interface holds a readable list of addresses.
What it is made of:
- hashed-address — a <address-list> list entry: the address in lowercase, hashed with SHA-256 and encoded as BASE64URL; /config/address-lists accepts the same entries;
- pmtahashedAddress — a utility from the distribution that computes this hash for a known address;
- privacy-policy — hides the local part of addresses in accounting: with a placeholder, or with a SipHash or HMAC-SHA256 hash with a key;
- digest — computes the keyed hash the same way, to find a known address’s records in accounting.
The parts have different scopes. Hashed entries live in the address list, the policy in the <acct-file> block, and the hashes are computed anywhere.
How they interact. These are two halves, and they do not match. The list hash is keyless and of the full address: the list cannot be read by eye, but a familiar address is checked against it instantly. The accounting hash is keyed and of the local part only: without the key, records cannot be linked either to an address or to the list. The price is the key: without it, support will not find an address’s records, and a lost key makes earlier records unlinkable forever.
The main trap is considering a keyless hash a secret. SHA-256 of an address is computed without a secret: the list cannot be read by eye, but a familiar address — or a whole address database — is checked against it instantly.
What the Hub does. It does not apply this: there are no suppression lists on the node. The Hub keeps warm-up unsubscribes in its own database and reconciles them with the mailing platform’s suppression, and in accounting recipient addresses go as is — privacy-policy is not set.
Recommended values
Two halves and their hashes:
| Half |
What is hashed |
How |
Who computes it |
| suppression list |
the full address in lowercase |
SHA-256 without a key, BASE64URL |
pmtahashedAddress |
| accounting |
the local part of the address in lowercase |
SipHash or HMAC-SHA256 with a key |
digest |
The hashed entry format, the utility, the accounting policy and the hash command come from the manual (§ 3.3.5.2, § 3.3.11.16, § 6.3.32, § 8.3.2). The analysis is ours; the scheme is a hypothesis.
Example configuration
<address-list suppressed>
hashed-address iZ0zh6XFp1VdUdLwoLe1Djl_5IH9mlj6-zibfclOEfY~</address-list>
<acct-file /var/log/pmta/acct.csv>
privacy-policy siphash "secret"
</acct-file>
The hash is from the manual’s example for test@foo.com; the accounting key is for illustration, the node needs its own.
yellow — — directive names, blue — blocks. They are highlighted the same way in the text of the card.