Chapter 39 — Quantum and post-quantum security: maintainability
Lesson map
Lesson 39 published. Map, example, EX077.
flowchart TD
N0["Learning outcomes"]
N1["39.1 Agility as maintainability"]
N2["39.2 Practical activity — Lab A"]
N3["39.3 Retirement"]
N4["39.4 Documentation and inventory"]
N5["Engineering note"]
N6["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6
N6 --> EX["Worked example"]
EX --> Q["Exercise EX077"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["39.1 Agility as maintainability"]
N2["39.2 Practical activity — Lab A"]
N3["39.3 Retirement"]
N4["39.4 Documentation and inventory"]
N5["Engineering note"]
N6["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> Q["EX077"]
[Learning outcomes]
|
v
[39.1 Agility as maintainability]
|
v
[39.2 Practical activity — Lab A]
|
v
[39.3 Retirement]
|
v
[39.4 Documentation and inventory]
|
v
[Engineering note]
|
v
[Synthesis]
|
v
[Worked example] --> [Exercise EX077]
Learning outcomes
You will (1) design for crypto-agility so future changes are cheap; (2) implement policy-driven algorithm selection; (3) manage algorithm retirement; and (4) keep inventory and documentation current. It builds on Chapters 9, 18 and 27.
39.1 Agility as maintainability
The post-quantum transition will not be the last: parameter sets may change, HQC and FN-DSA will arrive, and some algorithm may weaken. CSWP 39 describes agility across protocols, applications, hardware and infrastructure. Maintainable systems make algorithm change a routine operation measured in days.
BPA's target is that switching an algorithm on any service in scope takes days, not months. Lab A shows the pattern in a few lines: a registry of implementations, a policy that selects one, and an accept-list that controls what is still trusted. The time-to-replace metric tests whether that design holds in real systems, where hard-coded assumptions often hide.
39.2 Practical activity — Lab A
# Lab A (ch 39): crypto-agility through a policy-driven registry instead of hard-coded algorithms.
import hashlib, hmac
REGISTRY = {"hmac-sha256": lambda k, m: hmac.new(k, m, hashlib.sha256).digest(),
"hmac-sha3-256": lambda k, m: hmac.new(k, m, hashlib.sha3_256).digest()}
POLICY = {"tag-algorithm": "hmac-sha256", "accept": ["hmac-sha256", "hmac-sha3-256"]}
def protect(key, msg):
alg = POLICY["tag-algorithm"]; return alg, REGISTRY[alg](key, msg)
def check(key, msg, alg, tag):
if alg not in POLICY["accept"]: return False # algorithm identifier is authenticated by policy
return hmac.compare_digest(REGISTRY[alg](key, msg), tag)
k, m = b"k" * 32, b"meter reading 42"
a1, t1 = protect(k, m)
POLICY["tag-algorithm"] = "hmac-sha3-256" # migration = one policy change
a2, t2 = protect(k, m)
print("old tag still verifies during transition:", check(k, m, a1, t1))
print("new tag verifies:", check(k, m, a2, t2), "| algorithms:", a1, "->", a2)
POLICY["accept"] = ["hmac-sha3-256"] # retire the old algorithm
print("old tag after retirement:", check(k, m, a1, t1))
Expected output:
old tag still verifies during transition: True
new tag verifies: True | algorithms: hmac-sha256 -> hmac-sha3-256
old tag after retirement: False
The lab uses symmetric MACs to keep the code short; the pattern — registry, policy, accept-list, retirement — is identical for KEMs and signatures.
Notice the order of steps: the new algorithm is introduced while the old one stays on the accept-list, so existing tags still verify; only then is the old algorithm removed. Reversing the order would break every stored tag at once. The algorithm identifier travels with the tag but is checked against policy, so an attacker cannot choose a weak algorithm by changing the label. Add a third, deliberately weak algorithm to the registry and confirm it is rejected because policy does not accept it.
39.3 Retirement
Retiring an algorithm has phases: stop generating new uses; accept old uses during a transition window; reject after a date; remove code. Each phase is a policy change plus monitoring of residual use.
Monitoring residual use tells BPA when it is safe to move to the next phase: if classical-only handshakes have fallen to a handful of known clients, the reject date can be set and those clients contacted. Removing the code last prevents accidental reactivation by a configuration mistake. Each phase has a date published in advance so partners can plan.
39.4 Documentation and inventory
Keep the CBOM, interface control documents, policies and runbooks current through automation where possible (build-time CBOM generation, telemetry-fed dashboards). Stale documentation makes the next migration as hard as the first.
BPA treats documentation as part of the system: a build that changes cryptographic dependencies regenerates the CBOM, and a policy change updates the interface control document through the same pipeline. When documentation must be written by hand, such as runbooks, it has an owner and a review date. The goal is that the next migration starts from an accurate picture rather than another discovery project.
39.5 Worked example
BPA measures time-to-replace by switching the internal MAC algorithm on a test service through policy: 2 days including tests. The same exercise on a legacy service with hard-coded algorithms takes 6 weeks — a quantified case for refactoring.
Two days against six weeks gives a factor of about twenty, which makes the refactoring argument concrete for the budget holder. The six weeks come mostly from finding every hard-coded call site and testing each, the same work BPA's e-document service needed for its 41 rsa_sign() calls. Refactoring once removes that cost from every future change.
39.6 Common errors and limits
- Treating PQC migration as a one-time project.
- Accepting algorithm identifiers from untrusted input without policy checks.
- Retiring algorithms without monitoring residual use.
Treating PQC migration as a one-time project leaves systems as rigid as before, ready to repeat the effort when HQC or FN-DSA arrives. Accepting algorithm identifiers from untrusted input lets an attacker pick the weakest option, which Lab A prevents with its accept-list. Retiring without monitoring risks breaking clients that still depend on the old algorithm, which BPA avoids by publishing reject dates only after residual use is near zero.
Engineering note
Agility is also contractual. Procurement language should require vendors to support algorithm replacement through configuration, publish cryptographic inventories for their products, provide security updates for new algorithms within stated periods and disclose the libraries they embed. BPA adds these clauses to every new contract for appliances and software; over a hardware refresh cycle, the share of assets that can change algorithms without replacement rises, and the next migration becomes cheaper by design.
Exercises
- EX077 — Extend Lab A. Add a third algorithm and a retirement date check. Rubric: 3 = works and fails closed after the date.
- EX078 — Time-to-replace. Design a time-to-replace measurement for BPA's edge KEM. Rubric: 3 = start/end events and evidence defined.
Synthesis
Maintainability means agility: policy-driven algorithms, phased retirement, current inventory and a measured time-to-replace.
Continue studying — chapter 39 of 50
← Chapter 38 (draft) · Course chapter index · Chapter 40 (draft) →