Appendix D: Solutions for Chapter 30
This page collects solutions and editorial notes for the exercises in Chapter 30: Running a PQ migration program. Compute and derivation exercises have worked solutions; open-ended exercises have an editorial note describing what a strong answer addresses.
The fuller versions of these routines are in the migration_program package under solutions/ch30-migration-program. From a clone of the companion repository, pytest tests/ch30 runs its suite. Appendix C has the setup.
Exercise 1
Section titled “Exercise 1”Solution. The readiness gap is the weighted sum of (5 - score) over the seven PQRA domains. The priority is that gap times the quantum multiplier (3 for vulnerable) times the exposure multiplier (2 for public).
# Exercise 1: legacy_gateway scored against the Block 1 rollup.WEIGHTS = {"inventory": 0.20, "data_sensitivity": 0.15, "standards_compliance": 0.10, "migration_readiness": 0.20, "vendor_supply_chain": 0.15, "timeline_urgency": 0.10, "governance_policy": 0.10}
legacy_gateway = {"inventory": 3, "data_sensitivity": 2, "standards_compliance": 2, "migration_readiness": 1, "vendor_supply_chain": 2, "timeline_urgency": 1, "governance_policy": 3}
gap = sum((5 - legacy_gateway[d]) * w for d, w in WEIGHTS.items())priority = 3 * 2 * gap # vulnerable (3) x public (2)print(f"readiness gap {gap:.2f}, priority {priority:.2f}")
ranked = sorted([("blockchain_validator_sig", 18.00), ("legacy_gateway", priority), ("password_hashing", 1.60), ("webhook_hmac", 1.15)], key=lambda item: (-item[1], item[0]))for name, score in ranked: print(f"{name:<24} {score:.2f}")# ==> readiness gap 3.00, priority 18.00# ==> blockchain_validator_sig 18.00# ==> legacy_gateway 18.00# ==> password_hashing 1.60# ==> webhook_hmac 1.15legacy_gateway ties blockchain_validator_sig at 18.00. The rollup’s secondary sort is alphabetical on name, so blockchain_validator_sig lists ahead, and both sit above password_hashing and webhook_hmac. The first-wave mitigation owner is the modular cryptographic architecture area, since legacy_gateway is a vulnerable component that needs primitive replacement. Operational tooling and lifecycle management own the cutover, but architecture owns the design choice.
Exercise 2
Section titled “Exercise 2”Editorial note. The exercise has no canonical answer because the organization is fictional. A strong brief names the scope precisely (e.g. “all production cryptographic touchpoints in the customer-facing payments and identity domains. Excluded: research environments and offline backup tape encryption”), gives each phase a measurable exit criterion (e.g. Phase 1 “every component appears in the central CBOM and has a named owner” rather than “inventory complete”), names mitigation owners by role rather than by team identifier (e.g. “cryptographic architect for primitive selection” rather than “platform team”), and sizes the budget against engineer-quarters per touchpoint and license costs for any HSM upgrade required by the work. The trap: confusing the NCSC 2028 milestone (asset identification) with the 2031 first-wave or 2035 full-migration milestones. The brief is for 2028 specifically.
Exercise 3
Section titled “Exercise 3”Editorial note. A defensible answer takes one of the six risks the chapter names, pairs it with the owner the chapter assigns, and adds a signal that owner can actually report. Standards drift is the cleanest worked case. The owner is the governance-and-policy work-stream. The measurable signal is the count of deployed signers pinned to a composite-signature draft revision older than the current draft-ietf-lamps-pq-composite-sigs, reported each quarter. Two traps. The first is naming the program lead as the owner: the program lead aggregates risks but does not track IETF drafts. The second is answering with a cryptanalysis risk such as an ML-DSA tightness result. The chapter scopes that away in its opening line, which puts primitive and deployment attacks in the preceding chapters and the program-level threat surface here.
Exercise 4
Section titled “Exercise 4”Editorial note. Three patterns recur. Observability: no existing tool provides runtime PQC adoption metrics. Governance: composite OIDs require a new approval workflow that no existing change-management process covers. Modular architecture: the dependency tracker treats crypto libraries as opaque packages and cannot identify which vendored binaries embed RSA at link time. A useful answer names a specific, fixable gap inside one work-stream and proposes a concrete fix (e.g. “add a CBOM-fed dashboard panel that tracks per-NamedGroup handshake counts as a percentage of total”); a weak answer points at “people” or “budget” as the bottleneck, which lives outside the work-stream structure and is not actionable.
Exercise 5
Section titled “Exercise 5”Editorial note. Two of the five Ch 25 touchpoints still carry a classical component to retire: tls_endpoint_api, whose X25519MLKEM768 hybrid keeps a classical X25519 share, and jwt_signing, whose Ed25519+ML-DSA-65 composite keeps a classical Ed25519 half alongside the superseded RS256 kid. Both score 0.00 in the Block 1 rollup because the migration itself is done. What is left is the deprecation, which is what this exercise asks for. A defensible trigger is event-driven and reported by a specific work-stream (operational tooling reports the issuance count; observability reports the in-use count). The signal must be measurable in the existing telemetry, not speculative. “The team feels confident” is not a deprecation trigger. The trap: setting the trigger as “the deadline arrives” (calendar-driven), which retires the touchpoint regardless of actual readiness and produces incidents.