A code signature tells a device, an operating system or a user that a binary comes from you and has not been modified. That promise is only as strong as the protection of the signing key. A key in a file on a build server, in a CI secret or on a developer laptop can be copied, and a copied key signs malware that every one of your devices will accept.
This guide covers why signing keys belong in a non-exportable store, how remote signing works with the standard tools, what to sign (firmware, Windows binaries, Java archives, Git history, container images) and how DuoKey's code signing service implements it.
Table of Contents
- Why Signing Keys Must Not Be Exportable
- How Remote Code Signing Works
- What to Sign
- Controls That Make Signing Trustworthy
- Code Signing with DuoKey
- Limits to Plan For
- FAQ
Why Signing Keys Must Not Be Exportable
- Supply-chain attacks target signing. An attacker who signs with your key does not need to bypass any check: your own update path installs the payload.
- Public code signing already requires hardware. Since 1 June 2023, the CA/Browser Forum Baseline Requirements for publicly trusted code signing certificates require the private key to be generated and kept in a hardware cryptographic module (FIPS 140-2 Level 2 or Common Criteria EAL 4+, or a cloud service that meets the same bar).
- Device firmware lives longer. A firmware signing key often stays trusted for the whole life of a product line. Losing it can mean replacing the root of trust in devices already in the field.
- Regulation asks for integrity. The EU Cyber Resilience Act requires manufacturers to protect the integrity of software and updates; UN R155 and R156 ask the same of vehicle software updates.
How Remote Code Signing Works
With a non-exportable key, the private key never comes to the build machine. The build hashes the artefact, sends the digest (or a small payload) to a signing service, the vault or HSM signs it, and the signature goes back to the standard tool, which embeds it in the file.
- The build produces the artefact and computes its digest.
- The build authenticates to the signing service and sends the digest.
- The service checks policy (which application, which key, whether approval is needed) and has the vault sign.
- The signature returns to the tool (SignTool, the JAR signer, Git, cosign), which assembles the signed artefact.
- Every request is recorded: who asked, for which application, when, and whether it was approved.
Only a few bytes cross the network, so remote signing is fast even for large binaries.
What to Sign
| Artefact | Typical tool | Why it matters |
|---|
| Device firmware and update packages | Detached signature checked by the bootloader or update agent | Only authorised firmware boots or installs |
| Windows executables, drivers, installers (EXE, DLL, MSI, CAB) | Microsoft SignTool (Authenticode) | SmartScreen reputation, driver loading, enterprise policy |
| Java archives (JAR) | JDK JAR signing | Integrity of Java applications and plug-ins |
| Git commits and tags | Git SSH signing | Proves who changed the source, end to end |
| Container images | Sigstore cosign | Admission control in Kubernetes |
Controls That Make Signing Trustworthy
- One key per application, so a compromise or a revocation stays contained.
- Approval policies: require one or more approvers for release signatures, or for any signature with the production key.
- Separation of test and production keys, with production keys never used from developer machines.
- Timestamps (RFC 3161) on signatures that must stay valid after the certificate expires.
- A complete journal of every signature for incident response and audits.
- Algorithm agility: plan the move to post-quantum signatures (ML-DSA, SLH-DSA) for firmware that will still be verified in the 2030s.
Code Signing with DuoKey
DuoKey's code signing service is part of DuoKey PKI. A code signing application binds one non-exportable vault key, optionally a code signing certificate chain, and optionally an approval policy. Build machines and developers send a digest or a small payload to the signing API; the vault signs it; the signature goes back to the standard tool. The key never leaves the vault or HSM.
Supported tools
| Use | Tool | How it signs |
|---|
| Authenticode (EXE, DLL, MSI, CAB) | Microsoft SignTool | signtool sign /dg writes the digest, the DuoKey client has the vault sign it, signtool sign /di embeds the signature |
| Java archives | JDK JAR signing engine through the DuoKey JAR signer | The JDK builds the signature block; DuoKey performs the signature operation |
| Git commits and tags | Git SSH signing (gpg.format=ssh) with the DuoKey client as gpg.ssh.program | OpenSSH signature made with the application key |
| Container images | cosign generate / attach signature / verify | The signature payload is signed through the DuoKey client |
| Firmware and any detached signature | Any tool that can sign a digest or a small file over HTTPS | The DuoKey signing API |
Security model
- The generic key-signing API refuses a key bound to a code signing application, and one key backs at most one application per tenant, so a second application without approval cannot be pointed at the same key.
- An application can require every signature to be approved under a quorum policy.
- Weakening an approval policy or deleting an application itself requires approval.
The same platform issues the device certificates that verify your firmware: see PKI for IoT and secure over-the-air updates.
Limits to Plan For
- Authenticode needs a vault that signs precomputed digests (DuoKey software vault, Azure Key Vault or Managed HSM, Google Cloud KMS).
- The reference JAR signer does not add an RFC 3161 timestamp; use a timestamping step if signatures must outlive the certificate.
- Notation (Notary Project) signing and local PKCS#11 or Windows CNG providers for code signing are not provided; tools integrate through the remote signing API and the DuoKey reference clients.
- Kernel module and Office VBA macro application types use the same signing API but have no dedicated tool integration.
FAQ
What is a non-exportable signing key?
A key generated inside an HSM, a cloud KMS or a vault with export disabled. Applications can ask it to sign, but nobody, including administrators, can copy the private key out.
Do I need an HSM for code signing?
For publicly trusted code signing certificates, the CA/Browser Forum requires a hardware module or an equivalent cloud service. For private keys that sign firmware or internal software, a non-exportable vault key gives the same protection against copying.
How do I sign firmware with a key in an HSM?
Compute the firmware image digest in your build, send it to the signing service, and attach the returned signature in the format your bootloader or update agent verifies. With DuoKey, the signing API returns the signature for any digest, under the application's approval policy.
Can signing be approved by more than one person?
Yes. A DuoKey code signing application can require each signature to be approved under a quorum policy, which suits release signing with production keys.
How does code signing relate to the Cyber Resilience Act?
The CRA requires manufacturers to protect the integrity of software and security updates. Signing updates with protected keys, and verifying them on the device, is one of the standard ways to meet that requirement.