Chapter 19 — Identity and cryptography
Lesson map
Lesson 19 published. Map, example, EX018.
flowchart TD
N0["Learning outcomes and connection"]
N1["19.1 Primitives"]
N2["19.2 Authenticating telemetry"]
N3["19.3 Key management"]
N4["19.4 Identity for people and devices"]
N5["19.6 Practical activity: Lab 8"]
N6["Chapter synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6
N6 --> EX["Worked example"]
EX --> Q["Exercise EX018"]
Logical drawing
flowchart LR
N0["Learning outcomes and connection"]
N1["19.1 Primitives"]
N2["19.2 Authenticating telemetry"]
N3["19.3 Key management"]
N4["19.4 Identity for people and devices"]
N5["19.6 Practical activity: Lab 8"]
N6["Chapter synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> Q["EX018"]
[Learning outcomes and connection]
|
v
[19.1 Primitives]
|
v
[19.2 Authenticating telemetry]
|
v
[19.3 Key management]
|
v
[19.4 Identity for people and devices]
|
v
[19.6 Practical activity: Lab 8]
|
v
[Chapter synthesis]
|
v
[Worked example] --> [Exercise EX018]
Learning outcomes and connection
After this chapter you can (1) explain symmetric and public-key cryptography, hashes and MACs, and choose among them; (2) design message authentication with replay protection for constrained telemetry; (3) plan key management — generation, distribution, storage, rotation, revocation — for a field fleet; and (4) design identity and authentication for people and devices. It builds on Chapters 4, 13 and 18 and prepares Chapters 27–28.
19.1 Primitives
- Hash functions (SHA-256, FIPS 180-4) map data to a fixed-size digest; finding collisions or preimages should be infeasible. A hash alone authenticates nothing.
- Symmetric encryption (AES, FIPS 197) uses one shared key for confidentiality.
- Message authentication codes (HMAC, FIPS 198-1; RFC 2104) let holders of a shared key verify that a message is unaltered and came from a key holder.
- Public-key cryptography, introduced by Diffie and Hellman (1976) and realised for signatures by Rivest, Shamir and Adleman (1978), uses key pairs: anyone can verify a signature with the public key; only the private-key holder can sign.
- Authenticated encryption (e.g., AES-GCM) provides confidentiality and integrity together.
Never design your own primitives or protocols when a standard one fits; TLS 1.3 (RFC 8446) is the default for IP links that can run it.
19.2 Authenticating telemetry
For a constrained link, a common design is: payload plus a monotonic counter (or timestamp), MAC over both, receiver checks the MAC in constant time, then checks that the counter exceeds the last accepted value. The counter defeats replay; a timestamp with a freshness window defeats delay attacks but needs synchronised clocks. Truncating HMAC-SHA256 to 128 bits is common for bandwidth, with a correspondingly reduced but still very large forgery margin. Persist the last counter or rotate keys on restart, or a restart reopens replay (EX018).
19.3 Key management
Keys are where cryptography meets operations. Decide: who generates keys and where (ideally in hardware, never by hand); how they reach devices (factory provisioning, secure enrolment); where they are stored (secure elements, not configuration files); how they rotate (scheduled and after suspected compromise); how they are revoked; and who can access them. One key per device-pair limits the blast radius: compromising one RTU should not let an attacker impersonate another. A single fleet-wide key is a common cause with $\beta \approx 1$ (Chapter 7).
19.4 Identity for people and devices
People need named accounts, strong authentication (phishing-resistant multi-factor where possible — see NIST SP 800-63B), roles mapped to tasks, and prompt removal on departure. Devices need identities too — certificates or provisioned keys — so that a gateway knows which RTU it is talking to. Shared or default credentials are the most common identity failure in OT.
In TMRP, operators use named accounts with strong authentication at the SCADA servers, and each RTU has its own key, so the gateway knows which station sent each message.
19.5 Worked example: TMRP message format (synthetic)
ADR-007 chose HMAC with counters. The frame in Lab 8 carries an 8-byte counter, 2-byte station ID, 2-byte level and a 16-byte truncated HMAC-SHA256: 28 bytes, of which 22 are overhead relative to a 6-byte unauthenticated payload. Per-station keys are generated in the gateway's secure element at enrolment and stored in the RTU's key store; the SCADA side holds them in a hardware security module. Keys rotate annually and immediately on suspected compromise; the counter is persisted in non-volatile memory at each increment of 1,000 with a forward skip on restart, so replay of old messages remains impossible.
19.6 Practical activity: Lab 8
# Lab 8 - authenticated telemetry with a counter: tamper and replay are rejected (synthetic key, offline)
import hmac, hashlib, struct
KEY = bytes.fromhex("00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff") # demo key only
def seal(ctr, station, level_cm):
body = struct.pack(">QHH", ctr, station, level_cm)
return body + hmac.new(KEY, body, hashlib.sha256).digest()[:16]
class Receiver:
def __init__(self): self.last = {}
def accept(self, msg):
body, tag = msg[:12], msg[12:]
if not hmac.compare_digest(tag, hmac.new(KEY, body, hashlib.sha256).digest()[:16]): return "reject: tag"
ctr, st, lvl = struct.unpack(">QHH", body)
if ctr <= self.last.get(st, -1): return "reject: replay"
self.last[st] = ctr; return f"ok st={st} ctr={ctr} level={lvl}cm"
r = Receiver(); m1, m2 = seal(1, 3, 312), seal(2, 3, 309)
forged = m2[:10] + struct.pack(">H", 150) + m2[12:]
for name, m in [("m1", m1), ("m2", m2), ("replay m1", m1), ("forged", forged)]: print(f"{name:10}", r.accept(m))
print("frame bytes:", len(m1), "overhead vs 6-byte payload:", len(m1) - 6)
Expected output:
m1 ok st=3 ctr=1 level=312cm
m2 ok st=3 ctr=2 level=309cm
replay m1 reject: replay
forged reject: tag
frame bytes: 28 overhead vs 6-byte payload: 22
The key in the lab is a published demonstration value; real keys must never appear in source code.
The first two messages from station three are accepted with increasing counters. Replaying the first message is refused because its counter is not greater than the last accepted value, and the forged message, with its level changed from 309 to 150 centimetres, fails the tag check. The final line confirms the frame size used in ADR-007: twenty-eight bytes, twenty-two of them overhead. The lab keeps state only in memory, which is why EX018 asks what happens after a restart.
19.7 Common errors and limits
- Hashes or CRCs used as if they were MACs.
- Non-constant-time tag comparison.
- Replay protection lost on restart.
- Fleet-wide shared keys; keys in configuration files or source code.
- Default passwords and shared accounts.
- Cryptographic choices without a plan for the system's lifetime (algorithm agility).
TMRP's design answers each item: tags are compared in constant time, counters persist across restarts, keys are per station in secure hardware, and the message format gains a suite identifier for future algorithm changes. Each choice has a test.
Exercises — chapter 19
EX037 — Counter persistence. Objective: design restart-safe replay protection. Inputs: §19.5 (persist every 1,000 increments). Steps: explain why the RTU must skip forward on restart and by how much at least; state what the receiver must persist. Expected evidence: explanation. Rubric: 3 = skip ≥ 1,000 beyond last persisted value so no counter is reused, receiver persists last-accepted per station or rotates keys; 2 = one side only; 1 = vague; 0 = none.
EX038 — Blast radius. Objective: compare key designs. Inputs: 42 field stations; option A one fleet key; option B one key per station. Steps: compare the consequence of extracting a key from one stolen RTU, the rotation effort after that theft, and the storage required at SCADA. Expected evidence: table and recommendation. Rubric: 3 = A lets the thief forge any station and forces fleet-wide rotation; B confines forgery to one station with one rotation; storage trivial; recommendation B; 2 = one dimension missing; 1 = recommendation without reasoning; 0 = none.
Chapter synthesis
Choose standard primitives for the property you need: hashes for fingerprints, MACs or signatures for authenticity, authenticated encryption for confidentiality with integrity. Add freshness to defeat replay and keep it across restarts. Key management is the real system: per-device keys in hardware, rotation and revocation. Give people and devices distinct, strongly authenticated identities.
Continue studying — chapter 19 of 50
← Chapter 18 · Course chapter index · Chapter 20 →
Continue to the next authored lesson.