- How Code Signing Works: The Cryptographic Chain of Trust
- Where Code Signing Fits in the SDLC and DevSecOps Pipeline
- The CA/Browser Forum HSM Mandate: What Changed and Why It Matters
- Key Protection, Governance, and Compliance
- Cryptographic Agility and Quantum Readiness
- Common Pitfalls: Two Lessons From Real Incidents
- Code Signing Best Practices
- How Encryption Consulting Can Help
- Conclusion
Modern software is assembled, not written. A single release pulls in packages from open source, container base images, SDKs from outside vendors, and automated build pipelines. Each one is a potential entry point for an attacker. In that environment, the digital signature attached to a build is frequently the last verifiable statement that the bits a user runs are the bits your organization actually produced. Code signing is the practice of attaching a cryptographic digital signature to a software artifact so that anyone can verify who produced it and confirm it has not been altered. The discipline surrounding it, meaning how keys are generated, protected, used, and retired, decides whether the control holds up under attack.
The stakes are not theoretical. Gartner predicted that by 2025, 45% of organizations worldwide would experience a software supply chain attack, a threefold increase over 2021.
If anything, that forecast proved conservative. The Verizon 2025 Data Breach Investigations Report found that third parties were involved in roughly 30% of breaches, about double the share reported a year earlier.
This blog focuses on how code signing actually works, where it belongs in the software development lifecycle (SDLC), the end-to-end process through which software is planned, built, tested, released, and maintained, and the code signing best practices.
How Code Signing Works: The Cryptographic Chain of Trust
At its core, code signing binds an artifact to a publisher identity using asymmetric cryptography. The signing tool computes a cryptographic hash (a digest) of the artifact, then transforms that digest with the publisher’s private key to produce a digital signature. Anyone can verify the result with the corresponding public key by recomputing the hash and confirming that nothing changed after signing. Because the private key is never shared, verification stays open while signing remains tightly controlled.
That signature does not stand alone. It is packaged with the signer’s X.509 certificate and the chain of certificates leading back to a trusted root. Most signing formats, including Microsoft Authenticode, Java JAR signing, and Apple’s code signatures, build on the Cryptographic Message Syntax (CMS, RFC 5652), the IETF successor to PKCS #7. The verifier walks that chain in line with RFC 5280, checking validity dates, confirming the certificate carries the extended key usage for code signing, and testing revocation status through a CRL or OCSP.
One point deserves emphasis, because it is the root of the most damaging incidents: a valid signature proves where an artifact came from, not that the artifact is safe. If an attacker steals the private key or compromises the build pipeline that feeds the signer, the signature will faithfully certify malware. Code signing assures authenticity and integrity, and it is only as trustworthy as the key and the pipeline behind it.
Two further details trip up even experienced teams. The first is revocation. When a signing key is compromised, the certificate must be revoked, but revocation only protects verifiers that actually check it. The second is timestamping. A trusted timestamp is a countersignature from a timestamping authority (RFC 3161) that records when a signature was created. Without it, every signature effectively expires when the certificate does, and signing an entire back catalog again is rarely practical. With it, software signed while the certificate was valid keeps verifying long after the certificate expires. The catch, as the incidents later show, is that platforms which leniently accept expired or revoked certificates turn that convenience into an exploitable gap.
Where Code Signing Fits in the SDLC and DevSecOps Pipeline
Knowing how the cryptography works is only half the picture; where you place signing in the development process decides whether those guarantees actually hold. Code signing is most effective as a stage in the pipeline rather than a manual step bolted on before release. NIST’s Secure Software Development Framework treats protecting the integrity of released artifacts as a core practice. The reference pattern is simple to state: build, then sign, then verify. The architecture around it is what makes it durable.
Separate building from signing. The build system should not hold signing keys. It submits a hash or artifact to a dedicated signing service that controls the key, applies policy, and returns a signature. That keeps keys out of CI runners, the part of the pipeline most exposed to dependency and plugin compromise.
Sign only what you verified. Restrict signing eligibility to artifacts that passed integrity, provenance, and security checks. Signing an unverified build simply extends trust to something you never validated.
Verify on the way in, not only on the way out. Enforce signature verification at deployment, for example a Kubernetes admission controller that rejects unsigned or untrusted images. A signature nobody checks provides no protection.
The ecosystem has matured around these ideas. Supply chain frameworks such as SLSA define provenance levels, in-toto attestations capture verifiable metadata about how an artifact was built, and keyless approaches with very short lifetimes tied to OIDC identities and record signatures in a public transparency log, which shrinks the window in which a stolen standing key is useful. These approaches complement, rather than replace, signing released binaries with certificates. Yet all of them still rest on one assumption, that the signing key itself cannot be copied, and that is exactly the assumption a recent industry mandate set out to enforce.
The CA/Browser Forum HSM Mandate: What Changed and Why It Matters
The single biggest operational change to publicly trusted code signing took effect on June 1, 2023. Under the CA/Browser Forum’s Code Signing Baseline Requirements, private keys for both Organization Validation (OV) and Extended Validation (EV) code signing certificates must now be generated and stored in a hardware crypto module certified to at least FIPS 140-2 Level 2 or Common Criteria EAL 4+, and the key must be marked so that it cannot be exported.
It is worth noting that FIPS 140-2 is itself now being superseded by the newer FIPS 140-3. The CMVP stopped accepting new FIPS 140-2 validation submissions in September 2021 as part of the transition to FIPS 140-3. Existing FIPS 140-2 validated modules remain acceptable through September 21, 2026, after which they move to the Historical List and are generally intended only for existing systems rather than new procurements.
Certificate authorities verify this, often through remote key attestation, before issuing the certificate. The rationale is direct. Keys that live in software can be copied, stolen, and reused. Forcing keys into hardware that resists tampering, where they cannot be exported, dramatically narrows that attack surface. The cost is operational complexity. Once a key lives inside an HSM or token and cannot leave it, every signing operation must reach into that hardware. It must be handled properly because tokens do not scale across distributed build farms and a poorly integrated HSM becomes a bottleneck.
Key Protection, Governance, and Compliance
Hardware protection is necessary but not sufficient. A signing key in an HSM that anyone can invoke is still a single point of catastrophic trust. Governance is what makes the control meaningful.
Access control and separation of duties. Use access controls so that requesting, approving, and performing a signing operation are distinct roles. For your most important release keys, require dual control or quorum approval so no single person can sign alone.
Scoped credentials that expire quickly. Limit which keys a given pipeline may use and for how long and prefer ephemeral signing identities for CI over standing secrets.
Complete, immutable audit trails. Log every signing event centrally: who signed, which artifact, with which key, and when. This is both a detection control and an evidence base for ISO/IEC 27001, SOC 2, and PCI DSS audits.
A tested revocation and rotation plan. Know in advance how you would revoke a key, notify platform vendors, and issue a replacement, before you need to.
NIST’s foundational guidance, the Cybersecurity White Paper Security Considerations for Code Signing, details these architectural expectations and remains a useful reference for evaluating a signing solution.
Strong governance keeps signing trustworthy against the threats organizations face today. The harder question is whether the algorithms beneath it will still stand once quantum computing matures, which is where forward planning begins.
Cryptographic Agility and Quantum Readiness
Code that ships today, including firmware, medical devices, industrial controllers, and enterprise software that stays in service for years, may still be running when powerful quantum computers can break RSA and elliptic curve cryptography. Because that code must verify against keys embedded years earlier, code signing is one of the first places organizations should build cryptographic agility.
Cryptographic agility is the ability to change the algorithms a system relies on without re-engineering the system around them. In a signing context, that means treating the signature algorithm as a configurable choice rather than a hard-coded constant: abstracting it behind a signing service or interface, recording in every signature and certificate which algorithm produced it, and making sure verifiers can accept more than one scheme at once. Agility lets an organization introduce a new algorithm, run it alongside the existing one, and retire the old one on its own schedule, instead of scrambling to rebuild firmware.
In August 2024, NIST finalized its first standards designed to resist quantum computers: FIPS 204 (ML-DSA, a signature based on lattice cryptography) and FIPS 205 (SLH-DSA, a stateless signature based on hash functions).
For software and firmware signing specifically, NIST also approved two stateful schemes based on hash functions, LMS and XMSS, in Special Publication 800-208. Their security depends only on the strength of a hash function, a deliberately conservative assumption, and their stateful design makes them well suited to signing a limited, predictable number of releases.
The practical implications are real. The keys and signatures these algorithms produce are far larger than ECDSA or RSA, which affects firmware storage, update bandwidth, and verification time, as the comparison below shows. Stateful schemes such as LMS and XMSS also demand careful state management that survives crashes, because reusing a single use key is catastrophic, so they require dedicated HSM support and disciplined operations.
Approximate public key and signature sizes, in bytes:
| Scheme | Public key | Signature | Security level |
|---|---|---|---|
| ECDSA P-256 (classical) | 65 | 64 | ~128 bits |
| RSA-2048 (classical) | 256 (modulus size) | 256 | ~112 bits |
| ML-DSA-65 (FIPS 204) | 1,952 | 3,309 | NIST Level 3 |
| SLH-DSA-128f (FIPS 205) | 32 | 17,088 | NIST Level 1 |
Sizes are defined in FIPS 204 and FIPS 205.
The near term goal is not to rip and replace, but to inventory where signing algorithms are fixed in code, confirm HSM and tooling support, and design for swappable or hybrid algorithms. The NSA’s CNSA 2.0 timeline makes software and firmware signing the earliest transition of all. Though it binds only National Security Systems and their suppliers, it asks them to prefer the new algorithms by 2025 and use them exclusively by 2030, because firmware roots of trust are the hardest components to update after deployment. One subtlety matters for regulated environments.
For software and firmware signing, CNSA 2.0 approves ML-DSA, LMS, and XMSS for signing, but not SLH-DSA, even though SLH-DSA is also built on hashing. Its stateless, few-time signature design provides strong probabilistic resistance but leads to prohibitively large signature sizes and performance bottlenecks.
Common Pitfalls: Two Lessons From Real Incidents
Most signing failures fall into one of two categories. Either the key was stolen, or the pipeline that fed the signer was compromised. Two thoroughly documented incidents illustrate each.
Stolen keys (NVIDIA, 2022). When the Lapsus$ group leaked two NVIDIA code signing certificates, attackers used them to sign malware including Cobalt Strike beacons and remote access trojans. The certificates were already expired, yet Windows still accepted them for driver signing, a reminder that revocation and platform trust policies matter as much as the key itself.
A compromised pipeline (3CX, 2023). Attackers breached 3CX’s build environment and trojanized its desktop app. The malicious build was signed with 3CX’s own valid certificate, and the macOS version was even notarized by Apple, so it allowed the compromised software to pass trust checks and potentially reach 3CX’s customer base of more than 600,000 organizations. No key was stolen, and the signature was genuine. This is the clearest possible demonstration that a valid signature proves origin, not safety, and it shows why the build pipeline must be protected as one of your most sensitive systems.
The supporting failure modes are familiar: keys kept on developer laptops or in build scripts; signing without timestamps, so signatures silently expire; no inventory of which keys and certificates exist or when they lapse; and signing third party code on faith. Each one quietly widens the gap between “signed” and “trustworthy.” The good news is that every one of them is avoidable, and the best practices below show how to close that gap.
Code Signing Best Practices
The practices mentioned below include: how signing keys are generated and protected, how signing is governed and verified, and how the scheme stays agile as algorithms change. Treat them as a baseline to measure your current code signing practices, not a one-time setup.
- Keys in hardware, non-exportable. Generate signing keys inside the HSMs and mark them non-exportable so they can never leave the hardware. Isolate keys per product line or trust domain at the HSM partition level, so compromising one key never lets an attacker sign for another.
- Centralize signing behind a service. Centralize signing behind a dedicated service that holds the keys, enforces policy, and returns only a signature. Keep private keys out of CI runners, developer laptops, and build scripts, the parts of the pipeline most exposed to dependency and plugin compromise.
- Sign only verified artifacts. Sign only artifacts that have passed integrity, provenance, and security gates, and attach machine-verifiable provenance such as SLSA or in-toto attestations. Signing an unverified build simply extends trust to something you never validated.
- Timestamp every signature. Apply an RFC 3161 trusted timestamp to every signature so it keeps verifying long after the certificate expires. Without timestamps, you’d have to go back and re-sign every past release each time a certificate expires which is impractical when you have years of shipped products.
- Verify at the point of use. Enforce signature and policy verification at the point of use, not only at build time, whether that is a Kubernetes admission controller rejecting untrusted images or a bootloader refusing unsigned firmware. A signature nobody checks provides no protection.
- Separation of duties and M-of-N approval. Make requesting, approving, and performing a signing operation distinct roles under RBAC, and require M-of-N (quorum) approval for production and release keys so no single identity can both initiate and approve a signing. Keep the access policy itself version-controlled and auditable.
- Immutable, detailed audit trail. Record every signing event to append-only storage held separately from the signing infrastructure, capturing the artifact hash, key identifier, certificate, approving identity, and timestamp. This is both a detection control and the evidence base for ISO/IEC 27001, SOC 2, PCI DSS, and newer regimes such as the EU Cyber Resilience Act.
- Protect the build pipeline. Treat the build and signing pipeline as one of your most sensitive systems, with hardened runners, least-privilege service identities, and tamper-evident logging. As the 3CX breach showed, a valid signature on a compromised build still ships malware.
- Plan revocation and rotation. Document, automate, and rehearse how you revoke a key, notify platform vendors, and issue a replacement before an incident forces it. Where it fits, prefer short-lived or ephemeral signing identities, where the certificate is valid only briefly and the private key is discarded right after signing, so there is no standing key left to rotate, revoke, or steal.
- Build cryptographic agility. Build cryptographic agility for the post-quantum transition: inventory where signature algorithms are fixed in code (a CBOM helps), confirm HSM and tooling support for ML-DSA (FIPS 204) and the hash-based schemes in SP 800-208, and design for swappable or hybrid classical-plus-PQC signatures. Long-lived firmware shipped today must still verify against algorithms that resist a future quantum computer, so migrate on the CNSA 2.0 timeline rather than under deadline pressure.
How Encryption Consulting Can Help
CodeSign Secure is Encryption Consulting’s enterprise-class code signing management platform, designed to provide the infrastructure controls that industries need.
HSM-Backed Key Management
CodeSign Secure stores all private signing keys inside FIPS 140-2 Level 3 certified Hardware Security Modules, integrating with Thales Luna, Entrust nCipher, Utimaco, Securosys, and cloud HSMs from AWS and Azure. Per-product key isolation is enforced at the HSM partition level: each product line receives its own dedicated key, generated inside hardware and never exported.
M-of-N Signing Quorum and RBAC
The platform’s Role-Based Access Control model enforces M-of-N approval requirements for production firmware signing. No single individual can initiate and approve a signing operation. Signing requests, approvals, and rejections are all logged. The RBAC configuration itself is auditable and version-controlled, providing the documented signing policy that CRA conformity assessments require.
Immutable Audit Logging
Every signing event in CodeSign Secure generates an immutable log entry capturing the artifact hash, the key identifier, the certificate used, the approving identity, and the RFC 3161 timestamp. Logs are centralized, separately stored from the signing infrastructure.
Cross-Platform Firmware Format Support
CodeSign Secure supports signing of firmware artifacts across the full range of formats that a diverse product portfolio requires: .bin, .img, .hex, .fw, .dfu, and .efi, satisfying the CRA’s requirement for consistent controls across product lines without rebuilding the signing infrastructure for each platform.
Post-Quantum Cryptography Support
CodeSign Secure v3.02 supports production-grade ML-DSA (FIPS 204, at ML-DSA-44, ML-DSA-65, and ML-DSA-87 security levels) and SLH-DSA (FIPS 205) as detachable signatures alongside classical algorithms. For manufacturers building products with five-plus year CRA support obligations, PQC signing today is the architecture that protects against the HNDL threat before a CRQC arrives.
CI/CD Pipeline Integration
CodeSign Secure integrates with Azure DevOps, Jenkins, GitLab CI, and other major pipeline platforms through API and command-line interfaces. Firmware signing is a controlled, policy-enforced stage in the build pipeline, not a manual step.
Conclusion
Code signing is deceptively simple to describe and needs expert’s guidance to do well at scale. The cryptography is the easy part. The durability of the control comes from how keys are protected, how signing is woven into the SDLC, how verification is enforced, and how the whole system is governed and prepared for what comes next. Get the architecture right, with keys held in hardware, a centralized signing service, mandatory timestamping, enforced verification, strong governance, and a roadmap for cryptographic agility, and a signature becomes a trustworthy promise rather than a liability waiting to be stolen or forged.
If your organization is rethinking how it signs and protects software across the lifecycle, it is worth reviewing where your current practices stand against these benchmarks and deciding where to strengthen them next.
- How Code Signing Works: The Cryptographic Chain of Trust
- Where Code Signing Fits in the SDLC and DevSecOps Pipeline
- The CA/Browser Forum HSM Mandate: What Changed and Why It Matters
- Key Protection, Governance, and Compliance
- Cryptographic Agility and Quantum Readiness
- Common Pitfalls: Two Lessons From Real Incidents
- Code Signing Best Practices
- How Encryption Consulting Can Help
- Conclusion
