Articles

Code Signing Explained: How Software Proves Its Origin

Code signing attaches a digital signature to software so users can verify who published it and that it hasn't been altered. How it works and its limits.

Chisato Chisato · · 5 min read
A padlock in front of streaks of light

Code signing is the practice of attaching a cryptographic signature to software — an executable, installer, package, script, or container image — so that anyone who runs it can verify two things: who published it, and that it hasn’t been modified since it was signed. It’s the mechanism behind the operating system prompt that names a verified publisher, the warning you get for unsigned apps, and the integrity checks package managers run before installing anything.

What code signing actually proves

A valid signature answers two questions:

  • Authenticity. The code was signed by the holder of a specific private key, which a certificate ties to a named publisher.
  • Integrity. Not a single byte has changed since signing. A tampered binary, a corrupted download, or a malicious mirror swap all break the signature.

It does not prove the code is safe. A signature tells you who to blame, not whether the software behaves well. Malware signed with a stolen or fraudulently obtained certificate verifies perfectly.

How signing works step by step

Code signing is an application of digital signatures plus a certificate system to give the key an identity.

  1. Hash the artifact. The signing tool computes a cryptographic hash of the file (or of specific sections of it, depending on the format).
  2. Sign the hash. The hash is signed with the publisher’s private key, producing a signature that only that key could have created.
  3. Attach the certificate. The signature is bundled with the publisher’s certificate, which binds their public key to their identity and chains up to a trusted certificate authority.
  4. Timestamp it. A trusted timestamping authority countersigns the signature with the current time.

On the user’s machine, verification runs in reverse: the system rehashes the file, checks the signature against the public key in the certificate, and walks the certificate chain to a root it trusts. If any step fails, the OS or package manager warns or refuses to run it.

Why timestamping matters

Signing certificates expire. Without a timestamp, every piece of software signed with a certificate would suddenly fail verification the day it expired. A trusted timestamp proves the signature was made while the certificate was valid, so the software stays verifiable for years afterward. Timestamping also helps with revocation: if a key is compromised on a known date, signatures timestamped before that date can still be trusted while later ones are rejected. The mechanics of revocation are the same ones covered in OCSP vs CRL.

Where you encounter code signing

The concept is universal; the formats differ by platform.

  • Desktop operating systems. Windows and macOS both check signatures on executables and installers. macOS adds notarization, where Apple scans the signed app before it’s allowed to launch without warnings.
  • Mobile apps. Mobile platforms require every app to be signed, and updates must be signed with the same key as the original install — which is why losing an app signing key is a serious problem.
  • Linux packages. Distribution repositories sign package metadata with GPG keys, and the package manager verifies every download against keys installed on the system.
  • Container images. Images can be signed so that a cluster’s admission controller refuses to run anything that wasn’t signed by your build pipeline.
  • Scripts and drivers. Some environments require signed PowerShell scripts, kernel modules, or firmware before they’ll load.

The web has a lighter-weight cousin: subresource integrity pins a script to a known hash, which provides integrity but not publisher identity.

Code signing and the software supply chain

Signing has become central to software supply chain security. The modern goal is to sign not just the final artifact but statements about it — what source commit it came from, which builder produced it, and what dependencies it contains. Pairing signed artifacts with an SBOM and signed build provenance lets consumers verify the whole path from source to binary.

Keyless signing

Traditional code signing depends on a long-lived private key, which becomes a high-value target. Keyless signing, popularized by the Sigstore project, flips the model: the signer authenticates with an existing identity (such as a CI system’s workload identity or a developer’s login), receives a certificate valid for only a few minutes, signs, and discards the key. Every signature is recorded in a public, append-only transparency log — the same idea behind certificate transparency for TLS. Verifiers check that the signature appears in the log and that the identity matches what they expect.

Traditional vs keyless signing

Long-lived key signingKeyless signing
Key lifetimeYearsMinutes
Identity sourceCertificate from a CAOIDC identity (user or CI)
Main riskKey theftIdentity provider compromise
AuditabilityDepends on the publisherPublic transparency log
Best forOS-level app distributionOpen source packages, CI artifacts

The weak points

Key compromise. If an attacker steals a signing key, they can sign malware that every system trusts. Store keys in a hardware security module or a managed signing service so the key never leaves protected hardware.

Compromised build systems. If attackers inject code before signing, the signature faithfully certifies the malicious build. Signing protects what happens after the build, not the build itself. Isolated, reproducible builds and signed provenance close that gap.

Verification that never happens. A signature is worthless if nobody checks it. Pipelines that pull images or packages without enforcing signature policy get none of the benefit.

Over-trusting the signer. A signature proves who published something. It doesn’t prove their dependencies were clean or their intentions were good.

The takeaway

Code signing hashes software, signs that hash with a private key, and attaches a certificate that ties the key to a publisher, so users can verify origin and integrity before running anything. Timestamps keep signatures valid past certificate expiry, and keyless signing with transparency logs reduces the danger of long-lived keys. Treat signing as one layer of supply chain defense: protect the keys in hardware, secure the build that happens before signing, and make sure every consumer actually enforces verification.

Chisato Chisato · · 5 min read

What Is a JWKS? JSON Web Key Sets Explained

A JWKS is a JSON document of public keys that lets any service verify JWT signatures. How JSON Web Key Sets work, the kid header, caching, and key rotation.

#Security #Authentication #Cryptography