up:: In the Protocols MOC
Code Signing
Code signing is the practice of attaching a digital signature to software, a firmware image, a driver, or an update package, so that the system about to install or run it can verify two things before trusting it: that it came from a specific, known publisher, and that not a single byte has changed since that publisher signed it. The publisher signs with a private key only they hold, and every device that receives the code checks the signature with the matching public key, usually delivered inside a certificate that a certificate authority or a platform vendor vouches for.
The classical algorithms doing this job today, RSA, ECDSA, and Ed25519, all rest on math that a large quantum computer running Shor’s algorithm solves efficiently. Because signed firmware and boot code have to stay trustworthy for the decade or more a device stays in the field, code signing is one of the first and most consequential surfaces the post-quantum transition has to move.
The short version:
- Code signing attaches a digital signature to software or firmware so the installing system can prove who published it and that nobody altered it. Sign with the private key, verify with the public key.
- It’s the trust gate on operating-system updates, app stores, device drivers, secure boot, firmware images, and package registries. A system runs signed code and refuses or warns on code that’s unsigned or tampered.
- Classical code-signing algorithms are forgeable once a quantum computer runs Shor’s algorithm on the public key, which recovers the private signing key and lets an attacker forge any update that key was trusted to sign.
- Firmware and boot code are the sharpest exposure, because they’re long-lived. Anything signed today has to stay verifiable for the many years after a quantum computer arrives, so this is a migrate-early problem.
- The replacements are hash-based for the long-lived roots: CNSA 2.0 names the stateful LMS and XMSS for firmware and software signing, the stateless SLH-DSA removes their state-management hazard, and the general-purpose lattice signature ML-DSA fits higher-volume signing.
Think of a factory-sealed medicine bottle. You trust the pills inside because of two independent things at once: the manufacturer’s embossed hologram tells you the bottle came from the real company, and the intact tamper band tells you nobody opened it after it left the factory. If the hologram is missing or the band is broken, you don’t take the pills. Code signing is the software version of that bottle. The signature is the hologram and the tamper band fused into one mathematical check: it proves the publisher and it proves nothing changed in transit. The quantum problem is that Shor’s algorithm lets a counterfeiter print a perfect hologram from a photo of the real one, so the seal on tomorrow’s bottles stops meaning anything unless the seal itself is replaced.
What is code signing?
Code signing is a specific application of digital signatures to executable content: a publisher computes a signature over a piece of software or firmware with their private key, and the platform that installs or boots that code verifies the signature with the corresponding public key before trusting it. NIST describes the two guarantees it delivers plainly: data integrity, proving the code was not modified, and source authentication, identifying who signed it. Those are the same authenticity and integrity properties any signature gives, applied to the specific problem of distributing software that has to be trusted on a machine the publisher will never touch.
The mechanism is worth naming precisely, because code signing sits on top of a stack of other primitives:
- A digital signature is the core operation, computed over the code, that proves origin and integrity together.
- A hash function compresses the software (which can be gigabytes) down to a fixed-size digest, so one signature can cover an artifact of any size. The strength of the signature therefore depends on the strength of the hash underneath it.
- A signing certificate binds the publisher’s public key to their identity, so a verifier learns which named publisher the signing key belongs to, turning “signed by some key” into “signed by this specific company.”
- A trust anchor, either a public PKI root or a platform vendor’s built-in key, is what makes the certificate believable in the first place.
The reason code signing is a distinct topic rather than “just signatures” is the distribution model. The signer and the verifier never communicate directly, the signed artifact may sit in a repository for years before it’s installed, and the verifying device is often unattended, which is exactly the setting where a forged signature does the most damage.
Source: NIST, “Security Considerations for Code Signing,” Cybersecurity White Paper (CSWP 5), January 26, 2018, NIST.CSWP.01262018.
NIST, “Digital Signature Standard (DSS),” FIPS 186-5, February 2023, FIPS 186-5.
How does code signing actually work?
Code signing runs in three phases (signing, distribution, and verification), and the private key never leaves the publisher’s control while the public key travels everywhere the software goes. Walk it end to end:
- The publisher hashes and signs. The build system computes a cryptographic hash of the finished artifact, then signs that digest with the private signing key, ideally held inside a hardware module so the key can’t be copied off the build server. The signature and the signing certificate are packaged with the software.
- The code is distributed. The signed artifact moves through whatever channel the ecosystem uses: an update server, an app store, a package registry, or a firmware image baked onto a device. Nothing about the channel has to be trusted, because the signature is what carries the trust.
- The device verifies before trusting. The installing or booting system recomputes the hash of the code it received, checks the signature against the publisher’s public key, and validates that the signing certificate chains up to a trust anchor it already holds. Only if all three pass does the code get installed or allowed to run.
Firmware and secure boot add one more structural piece that ordinary application signing doesn’t have. NIST SP 800-193 describes a Root of Trust for Update (RTU): a protected component on the device that holds the signature-verification algorithm and the key store with the public key needed to check a firmware update, both stored so they can only change through an authenticated update. That RTU is what lets a device verify its own firmware before executing it, with nothing else on the machine to rely on yet. It’s the base of the chain, and it’s precisely why firmware signing is the least forgiving surface to migrate: the verifying key is often burned into hardware that ships and then lives untouched for years.
The security of the whole scheme reduces to two things staying true: the private key stays secret, and the underlying hard problem stays hard to reverse. For RSA that hard problem is integer factorization; for ECDSA and Ed25519 it’s the elliptic-curve discrete logarithm problem. Both are exactly what a quantum computer dissolves, which is the entire reason code signing is on the migration list.
Source: NIST, “Platform Firmware Resiliency Guidelines,” SP 800-193, May 2018, NIST SP 800-193.
Where is code signing used?
Code signing is woven through almost every path software takes to reach a running machine, and most of it is invisible until a signature fails and an install gets blocked. The high-stakes surfaces:
- Operating-system and application updates. Every major OS verifies a signature before applying an update, so a malicious patch can’t masquerade as a legitimate one. The signature is the line between a real update and malware wearing its clothes.
- App stores and mobile platforms. Mobile operating systems refuse to run an app whose signature doesn’t check out, which is how a platform vendor gates what executes on billions of devices.
- Device drivers. Kernel-mode drivers are signed because code running in the kernel has total control of the machine, so the platform will only load a driver whose signature traces to a trusted publisher.
- Firmware and secure boot. Secure-boot chains and firmware-update mechanisms verify a signature before letting code run at the lowest level of the device, anchored in the Root of Trust for Update. This is the longest-lived and least-swappable code-signing surface there is.
- Software packages and containers. Package registries and container-image ecosystems sign artifacts so a downstream system can confirm a dependency came from its real maintainer and wasn’t swapped in a supply-chain attack.
The common thread is that a broken code-signing scheme is a forgery problem, not a secrecy problem. The code was never meant to be hidden; the signature exists so a machine can decide whether to trust it. If the signature can be forged, an attacker doesn’t need to break into the distribution channel or steal anything. They can mint a signed update that every device accepts as genuine.
Source: NIST, “Security Considerations for Code Signing,” CSWP 5, January 26, 2018, NIST.CSWP.01262018.
Why is code signing a priority for post-quantum migration?
Code signing is a priority because it combines the two features that make quantum exposure worst: the signatures rest on the exact math a quantum computer breaks, and the things they protect live for years. A cryptographically relevant quantum computer running Shor’s algorithm efficiently solves both integer factorization and the discrete logarithm problem, so it takes a publisher’s public key, which is deliberately shared with the world, and recovers the private signing key. Once an attacker holds that key, they can forge any signature the key was trusted to make, and a forged update is designed to be indistinguishable from a real one.
Three things make this sharper for code signing than for most signature uses:
- The material an attacker needs is already public. The verification key sits inside every certificate and every device that checks the signature. There’s nothing to intercept and no vault to breach. The attacker needs the public key, which they already have, and the machine, which they’re waiting for. This is a forgery-side threat, not a harvesting one: nothing gets recorded, the attack is a real-time impersonation the day the machine exists.
- Firmware and boot code are long-lived. A device signed and shipped today may run for ten or fifteen years, and its firmware must stay verifiable that whole time. If the signing algorithm is forgeable before the device is retired, every unit in the field becomes a target for a forged update, and the verifying key may be burned into hardware that can’t be changed in place.
- The blast radius is enormous at the top. A platform vendor’s or an OS maker’s signing key underwrites trust across every device that accepts its updates. Forging one such key is close to arbitrary control over that whole population, which is why the collapse of a signing root is the worst case.
The reason this is a present-day problem even though the machine is years out is Mosca’s theorem: the time to migrate signing infrastructure (re-keying roots, updating verification code in firmware, re-signing artifacts, rolling new trust anchors to devices already in the field) plus the years a signed artifact has to remain trustworthy must both fit before the quantum computer arrives. For firmware, both of those numbers are large, so the clock is effectively already running.
Source: P. Shor, “Polynomial-Time Algorithms for Prime Factorization and Discrete Logarithms on a Quantum Computer,” SIAM J. Computing, 1997, quant-ph/9508027.
What replaces classical code-signing algorithms?
Classical code-signing algorithms get replaced by post-quantum signature schemes, and code signing is one of the few surfaces where the standards bodies point specifically at the conservative, hash-based family rather than the general-purpose lattice default. CNSA 2.0 names the stateful hash-based schemes LMS and XMSS for signing software and firmware in national-security systems, and NIST standardized them early for exactly this job in SP 800-208.
The right replacement depends on the role:
| Replacement | Standard | Basis | Best fit for code signing |
|---|---|---|---|
| XMSS | SP 800-208 | Hash-based, stateful | Firmware and software signing done inside an HSM, where volume is low and trust is long-lived; the CNSA 2.0 named choice |
| SLH-DSA | FIPS 205 (final) | Hash-based, stateless | Long-lived signing that wants the conservative hash foundation without the state-management hazard, at the cost of large signatures |
| ML-DSA | FIPS 204 (final) | Lattice (Module-LWE) | Higher-volume, general-purpose code and package signing where compact, fast signatures matter more than an alternate math assumption |
The pattern is that the deeper and longer-lived the trust, the more conservative the choice. For the firmware and boot roots that anchor everything, CNSA 2.0 points at LMS and XMSS, whose security rests only on a hash function, the oldest and most-studied assumption in cryptography, with no algebraic structure for Shor’s algorithm to attack. The catch is that these schemes are stateful: each key signs a fixed number of times and reusing a one-time key breaks the scheme, so SP 800-208 requires the signing to happen inside hardware.
Where a team wants the same hash-based conservatism without that state hazard, the stateless SLH-DSA is the option, trading state management for much larger signatures. For higher-volume signing that isn’t a decades-long root of trust, the lattice-based ML-DSA is the faster, more compact general-purpose default.
Sources: NSA, “Announcing the Commercial National Security Algorithm Suite 2.0,” September 2022, CNSA 2.0.
NIST, “Recommendation for Stateful Hash-Based Signature Schemes,” SP 800-208, October 2020, NIST SP 800-208.
NIST, “Stateless Hash-Based Digital Signature Standard,” FIPS 205, August 2024, FIPS 205.
Why does firmware signing get hash-based schemes instead of lattice?
Firmware signing leans on the hash-based schemes because it’s the one code-signing role where an alternate, maximally conservative math assumption is worth its operational cost. Three properties of firmware signing line up to make the case:
- It’s the longest-lived trust in the estate. A firmware root of trust may need to stay verifiable for the entire service life of a device, which can run past a decade. When a signing key protects something that far into the future, you want its security resting on the assumption least likely to see an unexpected break, and decades of cryptanalysis have found no shortcut against a strong hash function. That’s a smaller, older, better-studied set of assumptions than the lattice math under ML-DSA.
- The signing volume is low and controlled. Firmware and boot code are signed rarely, by a controlled authority that can host a hardware module, which is exactly the profile the stateful LMS and XMSS schemes need to manage their signing state safely. Their compact signatures are a bonus in constrained boot environments.
- The verifier is often frozen. The public key and verification code may be burned into a Root of Trust for Update that can’t be re-architected after the device ships, so choosing the most durable foundation up front matters more here than anywhere else.
Lattice signatures aren’t wrong for code signing in general. ML-DSA is the sensible default for high-volume application, package, and container signing, where its speed and smaller signatures win and the trust horizon is shorter. The split is by longevity and volume: the deep, decade-plus firmware roots go to the conservative hash-based family, and the everyday, high-throughput signing goes to the lattice default.
Source: NIST, “Recommendation for Stateful Hash-Based Signature Schemes,” SP 800-208, §1.1, October 2020, NIST SP 800-208.
When do classical code-signing algorithms have to be gone?
Two federal timelines set the deadline, and for code signing the aggressive one is CNSA 2.0, which puts firmware and software signing at the very front of its schedule. Its reasoning matches everything above: signed firmware has to outlive the arrival of a quantum computer, so it’s the first thing to move.
| Milestone | Year | What it means |
|---|---|---|
| Support and prefer CNSA 2.0 for software and firmware signing | 2025 | National-security systems begin adopting the post-quantum signing algorithms immediately |
| Exclusively use CNSA 2.0 for software and firmware signing | 2030 | Software and firmware signing must use only the approved post-quantum schemes, the earliest exclusive-use date in CNSA 2.0 |
| Classical signatures disallowed (all uses) | 2035 | NIST’s roadmap disallows classical public-key signature algorithms for federal use, with no exceptions |
The CNSA 2.0 software-and-firmware-signing exclusive-use date of 2030 is the front edge, five years ahead of the general 2035 horizon, precisely because these signatures anchor long-lived devices. On the broader civilian track, NIST IR 8547 deprecates 112-bit-strength classical signatures by 2030 and disallows all classical signature algorithms by 2035. Because insurers, sector regulators, and procurement programs align to these dates, they function as the practical industry timeline even for organizations that never touch a government contract, and the roots of trust (firmware anchors, code-signing authorities, certificate hierarchies) take the longest to migrate, so they start earliest.
Sources: NSA, “CNSA 2.0 FAQ,” PP-24-4014, December 2024 update, CNSA 2.0 FAQ.
NIST IR 8547 (Initial Public Draft), “Transition to Post-Quantum Cryptography Standards,” November 2024, NIST IR 8547 ipd.
Has code signing failed before?
Yes, and the most instructive failure is Stuxnet, the industrial-sabotage worm uncovered in 2010. To get its kernel-mode drivers loaded on Windows machines without tripping a warning, the operators signed them with legitimate code-signing certificates stolen from two real hardware companies, Realtek Semiconductor and JMicron, whose offices sat near each other in Taiwan. The signatures checked out, so the operating system loaded the malicious drivers as trusted code. Kim Zetter’s account in Countdown to Zero Day frames the whole operation around a pattern worth carrying into the quantum transition: every defensive control (code signing among them) functioned exactly as designed, and the attack succeeded anyway by satisfying the control rather than breaking it.
The line from Stuxnet to the quantum threat is direct. In 2010 the attackers had to physically steal the signing keys, which meant compromising specific companies and racing certificate revocation once the theft was discovered. A cryptographically relevant quantum computer removes the theft entirely: Shor’s algorithm derives the private signing key from the public certificate that every device already holds, so an attacker forges trusted code with no break-in, no insider, and nothing to revoke in time. Code signing’s guarantee has always been only as durable as the signing key’s secrecy, and a quantum computer dissolves that secrecy mathematically. That’s why re-keying the roots onto quantum-safe algorithms before the machine exists is the whole game.
Source: Kim Zetter, Countdown to Zero Day: Stuxnet and the Launch of the World’s First Digital Weapon, Crown, 2014.
Common misconceptions
- “A code signature encrypts or hides the software.” It doesn’t. A signature proves who published the code and that it wasn’t altered, while the code stays fully readable. A broken code-signing scheme is a forgery risk, not a data-leak risk, so the fix is a stronger signature algorithm rather than encryption.
- “Code signing only protects future releases, so quantum is a later problem.” Firmware and boot code signed today have to stay verifiable for the device’s whole service life, often a decade or more. Anything long-lived that’s signed with a classical algorithm now is already exposed to a future forger, which is why firmware signing migrates first.
- “A bigger RSA or ECDSA key will keep my signing safe from quantum.” For the classical signature algorithms, increasing key size buys almost nothing against Shor’s algorithm. The fix is switching to a post-quantum signature scheme, not enlarging a classical one.
- “Post-quantum code signing is a drop-in swap.” Same role, very different dimensions. Post-quantum signatures are far larger than elliptic-curve ones, and the stateful LMS and XMSS schemes add a hard requirement to sign in hardware and manage state, so it’s a planned migration touching build pipelines, firmware verification code, and trust stores.
- “If the signature verifies, the code must be safe.” A valid signature only proves the code came from the holder of that signing key and wasn’t altered. It says nothing about whether the code is benign or whether the key was stolen, as Stuxnet showed. Trust in the key itself comes from PKI and key management.
- “Every code-signing role should move to the same algorithm.” The standards split it by longevity and volume. Deep, long-lived firmware roots go to the conservative hash-based schemes, and high-volume application or package signing fits the faster, more compact lattice-based ML-DSA.
Questions people ask
What’s the difference between code signing and a regular digital signature? Code signing is a digital signature applied to the specific problem of distributing executable software and firmware. The cryptography is the same, but the setting is harder: the signer and verifier never talk directly, the artifact may sit for years before it’s installed, and the verifying device is often unattended, which is what makes a forged signature so damaging here.
Does code signing keep my source code secret? No. Signing proves who produced the code and that it wasn’t changed, but the code stays fully readable. Confidentiality is a separate job handled by encryption, with a separate key. Code signing proves trust rather than providing secrecy.
Which code-signing algorithms are quantum-vulnerable? The widely deployed classical ones: RSA, ECDSA, and Ed25519 (EdDSA). They all rest on integer factorization or the discrete logarithm problem, both of which Shor’s algorithm solves efficiently on a quantum computer.
What should firmware and software signing move to? CNSA 2.0 names the stateful hash-based schemes LMS and XMSS for firmware and software signing, run inside a hardware module. The stateless SLH-DSA is the hash-based option that removes the state-management hazard, and the lattice-based ML-DSA fits higher-volume general code signing.
Why do firmware roots use hash-based schemes instead of ML-DSA? Firmware roots are the longest-lived, lowest-volume, least-swappable trust in the estate, so an alternate and maximally conservative math assumption is worth its cost there. Hash-based security rests on the oldest, best-studied assumption in cryptography, which is what you want under a key that has to hold for a decade. Higher-volume signing, where speed and small signatures matter more, fits ML-DSA.
Do I have to re-sign everything right now? Not overnight, but the long-lived, high-privilege roots come first. CNSA 2.0 sets an exclusive-use date of 2030 for software and firmware signing, the earliest in its schedule, and NIST IR 8547 disallows classical signatures for federal use by 2035. Firmware anchors and code-signing authorities take the longest to migrate, so they start earliest.
Why are post-quantum code signatures a bigger engineering problem than a bigger CPU bill? Because the cost lands on size and process rather than raw compute. Post-quantum signatures and keys are much larger than elliptic-curve ones, which ripples into firmware images, verification code, transport limits, and update packaging, and the stateful hash-based schemes add a hardware-signing and state-tracking requirement. The migration is about certificates, parsers, build pipelines, and trust stores rather than raw signing speed.
Can an attacker forge signed code today? Not with a quantum computer, because a cryptographically relevant one doesn’t exist yet. Today’s forgeries still require stealing a signing key, as Stuxnet did. The quantum concern is that once such a machine exists, Shor’s algorithm lets an attacker derive the signing key from the public certificate, so a device signed with a classical algorithm now is exposed to forgery later.
Everything here is the map, given freely. When your team needs its own code-signing and firmware-signing estate found, its long-lived roots of trust sequenced onto a post-quantum path, and the signing keys re-anchored before the machine arrives, that’s the work I do. Request an alignment briefing.
Last verified 2026-07-09 · Maintained by Addie LaMarr, LaMarr Labs.