A reference pipeline for post-quantum code signing
Eight stages, mandatory dual signing, stateful key custody, and an illustrative signing-step config for moving code signing to post-quantum algorithms.
By 210 Security Research
A terminal manufactured in 2027 carries a verifier burned into ROM. In 2031 you re-sign its firmware with a post-quantum key, the build passes, the artifact is published, and the device refuses the update. Nothing in the pipeline is broken. The verifier simply has a fixed list of signature algorithms, written in silicon, and ML-DSA is not on it.
That failure is why a post-quantum signing migration is a pipeline project, not an algorithm swap. Signatures outlive the algorithms that produced them, because they are checked years after they are made. Fielded devices cannot renegotiate, because the verifier shipped before the question came up. And re-signing an artifact that has left the building is a re-release, with the qualification and distribution that implies.
The pipeline, stage by stage
The stages below are a reference, not a product. Each one exists because something downstream cannot be fixed later, and each one has to leave behind an artifact that proves it happened.
| Stage | Control | Evidence produced |
|---|---|---|
| Inventory and classify artifacts | Every signed artifact is registered with class, verifier population, field life, and owner | Per-release CBOM in CycloneDX, with artifact class and owner as properties |
| Key ceremony and HSM custody | Dual control, documented quorum, non-extractable keys, offline root for long-lived classes | Ceremony script, witness signatures, key attribute export |
| Algorithm selection by artifact class | A written decision per class, citing the authority that approves it | Signed ADR mapping class to algorithm and module |
| Parallel and dual signing | Sign twice, publish both, never convert the pipeline in place | Release manifest listing both signatures and their key identifiers |
| Verification and trust distribution | The verifier ships before the signer switches; trust stores are versioned artifacts | Verifier build matrix and trust store version ledger |
| State management for LMS or XMSS | Single writer, durable index ledger, reserved ranges per region | Index ledger export and an audit log of consumed indices |
| Re-signing fielded artifacts | Backlog tracked by class and verifier, with a confirmed update path per device generation | Re-signed manifest per release, plus a report of what remains classical |
| Rotation and retirement | Retire classical only after the last verifier that requires it is gone | Retirement record with the verifier decommission list attached |
The order is dependency, not difficulty: classification sets the algorithm, the algorithm sets the module, the module sets the ceremony, and the ceremony decides whether dual signing fits your timeline.
Dual signing is a distribution problem
Dual signing means two signatures over the same artifact: the classical one, so every verifier already in the field keeps working, and a post-quantum one, so verifiers shipped from now on have something to check. Signing twice is the easy part. Distribution is not.
You need a verification service that understands both, and a policy for what “verified” means while both are present. Require the post-quantum signature where the caller supports it, accept the classical one from a named list of legacy consumers, and log which was used. That log is how you learn when the classical path has gone quiet rather than merely unused by the services you instrumented.
Two costs are structural. Artifacts get larger, because post-quantum signatures are kilobytes rather than tens of bytes, and a dual-signed artifact carries both; that matters for bootloaders with fixed flash budgets, for update packages on metered links, and for archives that store signatures per release for a decade. Verification also costs more CPU and memory, which shows up first on constrained devices and in high-volume admission control. Neither is a reason to skip dual signing, and both are reasons to test on the verifier hardware you ship.
The sequencing rule is absolute: the verifier must accept both before the signer produces either alone. A pipeline that emits a second signature before any consumer can check it has added a failure mode without removing one.
Stateful signatures need an operational contract
LMS and XMSS, the schemes CNSA 2.0 requires for software and firmware signing via NIST SP 800-208, are stateful: each one-time key is used once, in sequence, and reuse breaks the scheme outright. Two signatures under the same index are enough to forge.
That produces a contract with the rest of your infrastructure.
Single writer. Exactly one process holds the authority to advance the index. Not a pool, not a leader-elected replica that can split brain during a partition, not a developer’s laptop running a recovery script.
A durable index ledger. The index and the signature commit together. If the signer crashes between consuming an index and writing the artifact, the safe outcome is losing the index, not reusing it.
No snapshots, no stale failover. Restoring a signing host from a VM snapshot or failing over to a replica with an older ledger can silently replay an index. This is the failure that looks like success: signatures verify, artifacts ship, and the key is compromised in a way no test will catch. Signing hosts should be treated more like a ledger than like a web tier.
Reserved index ranges for multi-region. Two regions signing concurrently need disjoint ranges assigned ahead of time, not a shared counter read at signing time. Rebalancing is a planned operation with a quorum, not an autoscale event.
Audit logging of consumed indices. Every signature records the index, the artifact digest, and the operator or job that requested it. That log is your only evidence that no reuse occurred, and it is the first thing a serious reviewer asks for.
Planned capacity. Tree height sets how many signatures a key can produce. Finishing the range early is a migration event with a lead time measured in quarters, so capacity planning belongs next to the rotation calendar rather than in the postmortem.
If your platform cannot meet all six, the honest answer for that artifact class may be ML-DSA where the profile permits it. That is a legitimate outcome, as long as it is a decision with a citation rather than a preference.
The validation queue belongs in the signing plan
FIPS 140-2 certificates moved to the CMVP historical list on September 21, 2026. FIPS 140-3 validation has averaged roughly 18 months, with 18 to 30 months a realistic planning range.
Procurement treats that number as a sourcing detail. It is a critical-path item for signing, for a specific reason: the signing step cannot be deployed on a module that is not validated at the firmware version you run, and the verifier that must accept the new signature has a hardware lead time of its own. Both clocks run in parallel, and the later one wins.
Work backwards. If your final classical verifier is manufactured in 2028, the new signature path has to be production-ready before that, which means the module was selected in 2027 and validation started then. A 2029 module decision produces a 2031 deployment at best, with no slack for a resubmission. Ask every vendor for the certificate number and the exact firmware version it covers, and treat “supports ML-DSA” without a certificate as a roadmap item.
Two related items belong here as well. Confirm that the validated module can do the operation you need, since signing and verification are not always in the same validated boundary. And confirm you can keep the classical public keys available for the archive, because retiring a signing key and deleting its public key are different operations and only one of them breaks verification of old releases.
A signing step, as configuration
The excerpt below is illustrative and not a real product configuration. It exists to show where the decisions live: algorithm per signature, key reference, state ledger, and the publish path.
# Illustrative only - not a product schema.
signing:
artifact_class: firmware
match: "firmware/terminal-*.img"
signatures:
- id: classical
algorithm: ecdsa-p256
key: "hsm://signing/terminal-fw-2026"
accept_until: "2031-12-31"
- id: pqc
algorithm: lms-sha256-m32-h15
key: "hsm://signing/terminal-fw-pqc-2028"
state_ledger: "ledger://signing/terminal-fw-pqc-2028"
index_range: "region-a: 0-1048575"
publish:
manifest: "release/manifest.json"
verify: "https://verify.internal/v2"
fail_closed: true
Three details carry weight. The accept_until date is the point at which the classical signature stops being required, not the date it stops being accepted, and conflating the two is how a legacy verifier gets stranded. The ledger reference is a separate resource from the key, because state custody and key custody fail differently. And fail_closed means an unavailable ledger blocks the release rather than falling back to a single signature, which is the right trade for firmware and the wrong one for a low-risk internal artifact.
The sequence
- Inventory every signing key and every verifier that trusts it, including the ones inside appliances and the ones embedded in vendor trust stores.
- Classify artifacts by verifier population and field life. Firmware with a burnt-in verifier is a different class from a container image pulled daily.
- Pilot on one artifact class, not one service. A pilot that spans classes teaches you nothing about the class with the hard constraints.
- Dual-sign in a parallel pipeline, with the verifier shipped first and the verification service logging which signature each consumer used.
- Re-sign the fielded backlog in dependency order, tracking what remains classical and which device generations cannot be reached.
- Retire classical only after the last verifier that requires it is decommissioned, then keep the public keys for archive verification.
The gate between each step is the same: evidence exists, the verifier is in the field, and rollback has been tested. A stage that ends without those three is a stage you will run twice, and the second run will be on a shorter deadline.
Sources
About this writing
Published by 210 Security Research. We cite primary sources for regulatory claims and label drafts as drafts. If you find an error, tell us and we will correct it in public.