Chapter 24 — Cryptography and trust services: methods I
Lesson map
Lesson 24 published. Map, example, EX070.
flowchart TD
N0["Learning outcomes"]
N1["24.1 Why derive keys"]
N2["Lab — HKDF against RFC 5869"]
N3["24.2 Reading the HKDF run"]
N4["24.3 Context and separation"]
N5["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5
N5 --> EX["Worked example"]
EX --> Q["Exercise EX070"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["24.1 Why derive keys"]
N2["Lab — HKDF against RFC 5869"]
N3["24.2 Reading the HKDF run"]
N4["24.3 Context and separation"]
N5["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX070"]
[Learning outcomes]
|
v
[24.1 Why derive keys]
|
v
[Lab — HKDF against RFC 5869]
|
v
[24.2 Reading the HKDF run]
|
v
[24.3 Context and separation]
|
v
[Synthesis]
|
v
[Worked example] --> [Exercise EX070]
Learning outcomes
You will (1) derive many keys from one master key with HKDF; (2) verify an implementation against published test vectors; (3) separate keys by purpose with context information.
24.1 Why derive keys
Ridgeway needs separate keys for each meter and each purpose. Storing 50,000 random keys is possible, but deriving them from a master key in the key service simplifies backup and provisioning. HKDF, specified in RFC 5869, does this in two steps: extract concentrates the entropy of input keying material into a pseudorandom key using HMAC with a salt, and expand produces as many output bytes as needed, bound to an info string describing the purpose. Different info strings yield independent keys, so a telemetry key cannot be confused with a firmware key.
Lab — HKDF against RFC 5869
"""Check HKDF-SHA256 against RFC 5869 test case 1 (teaching only: use a vetted library in production)."""
import hmac, hashlib
def hkdf(ikm, salt, info, length):
prk = hmac.new(salt, ikm, hashlib.sha256).digest() # extract
okm, t, i = b"", b"", 1
while len(okm) < length: # expand
t = hmac.new(prk, t + info + bytes([i]), hashlib.sha256).digest(); okm += t; i += 1
return prk, okm[:length]
def main():
prk, okm = hkdf(bytes([0x0b]) * 22, bytes(range(13)), bytes(range(0xf0, 0xfa)), 42)
want = "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"
print("PRK", prk.hex()[:32], "...")
print("OKM matches RFC 5869 A.1:", okm.hex() == want)
a = hkdf(b"utility-master-demo", b"salt", b"telemetry-tls", 16)[1].hex()
b = hkdf(b"utility-master-demo", b"salt", b"firmware-sign", 16)[1].hex()
print("different info, different keys:", a != b)
if __name__ == "__main__":
main()
Run with python3 lab_hkdf.py. Verified output:
PRK 077709362c2e32df0ddc3f0dc47bba63 ...
OKM matches RFC 5869 A.1: True
different info, different keys: True
24.2 Reading the HKDF run
The lab implements HKDF with hmac solely to make the two steps visible, and checks it against RFC 5869 test case A.1: the 42-byte output matches exactly. It then derives two keys from the same demonstration master with different info strings, telemetry-tls and firmware-sign, and confirms they differ. Aiyana writes beside the code that Ridgeway's production key service uses a vetted library's HKDF; the purpose of the exercise is to understand and verify behaviour, not to deploy a hand-written version. A matching test vector proves correct use, not side-channel safety.
24.3 Context and separation
Aiyana designs info strings carefully: they include purpose, meter identifier and key version, such as "ridgeway/reading-hmac/M-0417/v3". Including the version allows rotation by deriving a new key without changing the master. Including the meter identifier makes each meter's key unique. She warns against reusing one derived key for two purposes, such as tagging readings and encrypting configuration, because a weakness or misuse in one use could compromise the other. Key separation is a cheap, powerful design habit. She documents the label format so all teams derive keys identically.
Worked example
Aiyana verifies HKDF behaviour against RFC 5869 A.1, then specifies info strings that encode purpose, meter identifier and version for per-meter, rotatable keys.
Synthetic case. The master key and labels are invented; RFC 5869 and its test vector are real.
Errors and limits
HKDF does not add entropy; a weak master key yields weak derived keys. Hand-written versions are for learning only.
Exercises
- EX070 — Extract and expand. What do HKDF's two steps do? Rubric: 3 = extract makes a pseudorandom key from input material with a salt; expand outputs bytes bound to info;; 2 = one step;; 1 = encryption;; 0 = none.
- EX071 — Test vector result. What did the lab print for the RFC 5869 check? Rubric: 3 = OKM matches RFC 5869 A.1: True;; 2 = True;; 1 = False;; 0 = none.
- EX072 — Info string design. What does Aiyana put in info strings and why include the version? Rubric: 3 = purpose, meter identifier, version; version enables rotation without changing master;; 2 = partial;; 1 = random;; 0 = none.
Synthesis
HKDF derives many separated, rotatable keys from one well-protected master, and test vectors confirm correct use.
Continue studying — chapter 24 of 50
← Chapter 23 (draft) · Course chapter index · Chapter 25 (draft) →