◇ OpenCyber Academy
Technologist · Chapter 17 · English

Chapter 17 — Pseudonymisation for extracts

Open, free learning for anyone who wants to protect people and technology. No account is required to read this text or its worked answers.

Chapter 17 — Pseudonymisation for extracts

Lesson map

Lesson 17 published. Map, example, EX049.

flowchart TD
  N0["Learning outcomes"]
  N1["17.1 The need"]
  N2["Lab — Keyed-hash pseudonyms for tenant identifiers i"]
  N3["17.2 How it works"]
  N4["17.3 Protecting the key"]
  N0 --> N1 --> N2 --> N3 --> N4
  N4 --> EX["Worked example"]
  EX --> Q["Exercise EX049"]

Logical drawing

flowchart LR
  N0["Learning outcomes"]
  N1["17.1 The need"]
  N2["Lab — Keyed-hash pseudonyms for tenant identifiers i"]
  N3["17.2 How it works"]
  N4["17.3 Protecting the key"]
  N0 --> N1 --> N2 --> N3 --> N4 --> Q["EX049"]
[Learning outcomes]
    |
    v
[17.1 The need]
    |
    v
[Lab — Keyed-hash pseudonyms for tenant identifiers i]
    |
    v
[17.2 How it works]
    |
    v
[17.3 Protecting the key]
    |
    v
[Worked example] --> [Exercise EX049]

Learning outcomes

You will (1) pseudonymise identifiers with keyed hashes; (2) preserve linkage for analysis; (3) explain the limits of pseudonymisation.

17.1 The need

An analyst wants to study whether some tenants report the same problem repeatedly, which could indicate poor repairs. The study needs to link jobs for the same tenant but not to know who the tenant is. Ravi proposes replacing tenant identifiers with pseudonyms in the extract. He explains that pseudonymisation reduces risk if the extract is lost or misused, while still allowing the analyst to count jobs per tenant and look for patterns. The tenancy owner approves the extract with pseudonyms in place.

Lab — Keyed-hash pseudonyms for tenant identifiers in a synthetic extract

"""Mask tenant identifiers in a synthetic extract with keyed hashes and check linkage (stdlib only)."""
import hmac, hashlib
key = b"synthetic-teaching-key"
def p(t): return hmac.new(key, t.encode(), hashlib.sha256).hexdigest()[:12]
rows = [("T1001", "leak"), ("T1002", "boiler"), ("T1001", "damp"), ("T1003", "lock"), ("T1001", "leak")]
masked = [(p(t), j) for t, j in rows]
print(f"rows {len(rows)}; distinct tenants {len({t for t,_ in rows})}; distinct pseudonyms {len({t for t,_ in masked})}")
print(f"T1001 pseudonym {p('T1001')}; jobs linked {sum(1 for t,_ in masked if t == p('T1001'))}")

Run with python3 lab_mask.py. Verified output:

rows 5; distinct tenants 3; distinct pseudonyms 3
T1001 pseudonym 083752155d81; jobs linked 3

17.2 How it works

The lab uses Python's hmac and hashlib modules to create a keyed hash of each tenant identifier with a secret key held by the data team. In a five-row synthetic extract with three distinct tenants, the result has three distinct pseudonyms. Tenant T1001 becomes 083752155d81, and all three of that tenant's jobs share the same pseudonym, so the analyst can see that one tenant had three jobs, including two leaks, without knowing the identifier. The analyst confirms that the linkage meets the study's needs.

17.3 Protecting the key

The key is what makes pseudonyms hard to reverse. Without the key, someone with a list of tenant identifiers cannot recompute pseudonyms. Ravi stores the key in the data team's restricted vault, not in the script, and limits access to two people. He sets a rule that the same key is used only for one project, so pseudonyms from different extracts cannot be linked by others. Each use of the key is recorded. Access to the vault is reviewed every quarter by the owner.

17.4 Limits

Ravi explains that pseudonymised data remain personal data under the GDPR, because the data team can re-identify tenants with the key and because other details, such as a rare repair at a specific property, might identify someone. The extract therefore still needs access controls and a retention date. Ms. Moreau notes that pseudonymisation is a valuable safeguard but not anonymisation, and that NIST SP 800-188 discusses why de-identification must consider all fields together. The extract is given a deletion date at the end of the analyst's study.

Worked example

Ravi pseudonymises tenant identifiers with keyed hashes, keeps three tenants as three pseudonyms with T1001's three jobs linked, protects the key in a vault per project and explains that the extract remains personal data.

Synthetic case. The extract and key are synthetic; outputs come from lab_mask.py; the GDPR and NIST SP 800-188 are real.

Errors and limits

Plain hashes without a key can be reversed by hashing known identifiers.

Exercises

Continue studying — lesson 17 (chapter 17 of 30)

← Chapter 16 · Course chapter index · Chapter 18 →

Continue to the next authored lesson.