A valid digital signature connects a message to a public key. However, it does not establish who owns that key. An attacker who controls a download page can replace the software, sign it with the attacker’s own private key, and present the corresponding public key as the publisher’s. The signature will verify if the receiver accepts that substituted key. Verifying an update therefore requires establishing that the public key belongs to the actual publisher.
One approach is to obtain the public key through an already trusted channel. An installer obtained from a trusted source can include the publisher’s verification key for future updates. A key fingerprint, which is a hash of a public key, provides another way to check a key. The recipient compares the received key’s fingerprint with a fingerprint obtained from a trusted source.
Obtaining a trusted key separately for every website would be impractical. Browsers instead rely on authorities that issue digitally signed statements linking website names to public keys. A browser checks those signatures and follows the links back to an authority it already trusts.
Digital Certificates
A digital certificate binds a public key to an identity, such as a website name or a software publisher. It contains the identity, the key, and an issuer’s digital signature asserting that they belong together. Web certificates use the X.509 format, originally developed as part of an international directory standard.
A certificate holds a small number of fields:
-
Subject. Information about the party the certificate describes, such as an organization. The website names appear in an extension.
-
Subject public key. The key being bound to that identity.
-
Issuer. The party that signed the certificate.
-
Validity period. The dates before and after which the certificate is not to be accepted.
-
Extensions. Additional constraints, including the full list of domain names the certificate covers and whether the key may be used to sign other certificates.
-
Signature. The issuer’s signature over all of the above.
The parties that issue certificates are certificate authorities (CAs). Before issuing a web certificate, a CA checks that the applicant controls the requested domain name. The applicant may have to place a particular value on the website or in its DNS records. A publicly trusted CA must follow the validation rules required by browser and operating system vendors.
This process is called domain validation. It establishes control of a name, not that the website is honest or safe. Other certificate types include additional checks on the organization behind the name, but even those cannot establish that everything the organization publishes is trustworthy.
Certificate Chains and Trust Stores
A browser also needs a reason to trust the CA’s public key. Certificate chains provide that connection and are a routine part of HTTPS connections. A website’s certificate is usually signed by an intermediate CA, whose certificate leads back to a trusted root CA. A chain with one intermediate works like this:
Root CA's public key, already trusted by the browser
verifies the signature on the intermediate CA's certificate
Intermediate CA's public key
verifies the signature on the website's certificate
Website's public key
The root is the starting point the browser already trusts, called a trust anchor. A trust store is the collection of root certificates and trust settings accepted by the browser or operating system. Its vendor decides which authorities to include and can remove an authority that no longer meets its requirements.
Intermediates allow a CA to keep its root private key offline while using separate keys for day-to-day certificate issuance. Let’s Encrypt, a nonprofit certificate authority, issues website certificates through intermediate CAs and keeps its root keys offline. A browser may follow several intermediate certificates before reaching a root it trusts.
The server normally sends its own certificate and the intermediate certificates needed to complete the chain. The browser supplies the trusted root from its store. Sending a root certificate does not make it trusted: that decision must already have been made independently. Root certificates are commonly self-signed, but anyone can create a self-signed certificate.
Checking a Website’s Certificate
To authenticate a website using its certificate, the browser checks several things:
-
The website’s certificate covers the requested domain name and is within its validity period.
-
The certificate signatures lead through valid intermediate certificates to an accepted trust anchor. Each intermediate must be authorized to issue the certificates below it.
-
The certificates meet the browser’s security requirements, including its rules for checking whether certificates have been revoked.
-
The server demonstrates possession of the matching private key. In TLS 1.3, it signs data from the current connection’s handshake.
The last check matters because a certificate is public. Anyone can copy a bank’s certificate, but the copy does not include the private key needed to authenticate a new connection.
Rejecting a Certificate Before It Expires
A certificate may need to be rejected before its expiration date because its private key was stolen or the CA issued it incorrectly. Withdrawing that certificate is called revocation. The difficulty is getting the withdrawal notice to the machines that might otherwise accept it.
A certificate revocation list (CRL) is a signed list published by a CA identifying certificates it has revoked. A client can download the list and check a certificate’s serial number against it. However, downloading a large list to check one certificate wastes bandwidth, and a cached list can become stale between updates.
The Online Certificate Status Protocol (OCSP) was designed to let a client request the status of one certificate without downloading a whole CRL. The client sends a query and receives a signed status response. A direct query can add delay and reveal which site the client is visiting. It also creates a difficult choice when the responder is unreachable: reject a possibly legitimate connection, or proceed without knowing whether the certificate was revoked. Some clients proceed, allowing an attacker who blocks the query to suppress a revocation check.
A server can instead obtain a recent signed OCSP response and include it when establishing the connection. This is called OCSP stapling, and it avoids requiring a separate client query. Browsers can also distribute revocation information for local checks. Firefox uses CRLite to compress revocation information and check domain-validated certificates locally.
Shorter certificate lifetimes provide another limit on exposure. Once a certificate expires, a browser rejects it even if an attacker still holds the stolen private key. Short lifetimes reduce the window of risk, but they do not remove the need to revoke a compromised certificate during that window.
Certificate Transparency
Revocation is useful only after someone discovers a problem. A trusted CA can issue a certificate for a domain without the domain owner’s knowledge, either by mistake or after a compromise. Unless the CA’s authority is restricted, that certificate can be accepted by browsers that trust the CA.
In 2011, attackers compromised DigiNotar, a Dutch certificate authority, and issued fraudulent certificates, including one used to intercept Google traffic in Iran. The certificates carried valid CA signatures, even though the real domain owners had not authorized them. Browser and operating system vendors removed trust in DigiNotar.
Certificate Transparency makes certificate issuance visible through public logs. Domain owners and monitoring services can search those logs for unexpected certificates. Hashes and signatures make changes to a log’s published history detectable, so the log operator cannot quietly rewrite that history without leaving evidence.
Chrome requires publicly trusted website certificates to carry signed receipts from recognized logs. Each receipt promises that the certificate will be included in the log within a specified time. Monitoring can detect unfulfilled promises and unauthorized certificates. Transparency helps expose incorrectly issued certificates, but it does not prevent a CA from issuing them.
Code Signing
Authenticating a website protects a connection. Downloaded software also needs protection after the connection ends, when the file is copied, stored, or installed.
Code signing attaches a digital signature to software so that its origin and integrity can be checked later. The publisher signs a digest of the code with a private key. The installer or operating system checks the signature and establishes whether the signing key belongs to an accepted publisher, often by verifying a certificate chain.
A successful check shows that the signed content has not changed and was signed using the private key associated with that publisher. Whether the program is safe to run is a separate question that no signature answers.
Platforms apply these checks in different places:
-
Windows uses Authenticode to identify the signer of an executable and detect changes to its signed content. Signing requirements are stricter for kernel drivers than for ordinary applications.
-
iOS requires applications to carry valid code signatures, with the permitted signing identities controlled by Apple’s distribution rules.
-
macOS uses Gatekeeper to check downloaded applications. Under its default policy, applications distributed outside the App Store generally need an Apple-issued Developer ID signature and notarization. Notarization means submitting the software to Apple for automated checks and receiving a signed ticket that macOS can verify.
-
Linux distributions commonly verify software through their package managers. Debian and Ubuntu verify signed repository information containing package digests, while Fedora signs individual software packages.
An executable may be loaded into memory a page at a time. Apple’s code-signing format includes a signed table of page digests, allowing the kernel to check code pages as they are loaded. This ties the check to the bytes being loaded, rather than relying only on an earlier check of the file.
Signature checks can also begin before the operating system runs. In secure boot, firmware checks the bootloader before executing it, and verification continues through later stages of startup. The initial verification key is protected by the device’s firmware or hardware. A valid chain of checks prevents an attacker from replacing a startup component with code that lacks an accepted signature.
What a Valid Signature Does Not Prove
A publisher can sign software that contains a serious vulnerability or deliberately harmful behavior. A signature identifies the signing key and protects the signed content against changes, and says nothing about what the program does.
Nor does a signature establish that the publisher reviewed the exact code being signed. A build system compiles source code into an executable and may pass it automatically to a signing service. If an attacker inserts malicious code before that point, the publisher’s own release process can produce a correctly signed malicious program.
Software Supply Chain Attacks
A software supply chain attack compromises software through the people, tools, or components involved in producing and distributing it. An attacker can steal a signing key, alter the build process, or insert malicious code into a dependency. Each route can produce software that passes a signature check, but the defenses differ.
Stolen Keys and Forged Certificates
The most direct approach is to sign malicious code with a key that machines already trust.
Stuxnet, discovered in June 2010, targeted industrial control systems in Iranian uranium enrichment facilities. Its malicious drivers were signed using private keys stolen from Realtek Semiconductor and JMicron Technology, two Taiwanese hardware manufacturers. Windows accepted the signatures because they verified under the manufacturers’ legitimate certificates.
Flame, discovered in May 2012, used a forged certificate instead. A Microsoft licensing service issued certificates signed using MD5. Flame’s authors exploited MD5 collisions to obtain a signature that also verified for a forged certificate, allowing their code to appear to come from Microsoft. Flame used that apparent authority to distribute malicious updates on local networks. This is the collision attack described earlier applied to a certificate: a signature on one set of bytes also verified for a different set with the same digest.
Stuxnet exploited the loss of a private key; Flame exploited a weakness in the hash function. Both attacks allowed outsiders to claim a trusted publisher’s identity.
Tampering with the Build
An adversary who cannot obtain the signing key can instead alter what the key is asked to sign.
In 2020, an intruder gained access to the build environment of SolarWinds, a company whose Orion product monitors corporate and government networks. The attacker inserted malicious code during the build, leaving the source repository unchanged. SolarWinds signed the result with its own key and distributed it as an update. Up to 18,000 customers installed the affected updates, and the intruders selected a smaller number for further intrusion, including several U.S. federal agencies. FireEye, a security company, discovered the compromise in December 2020 while investigating a breach of its own network.
The signature correctly established that SolarWinds had signed the file. It could not reveal that the build system had inserted code the developers never intended to release. Protecting the signing key alone would not have prevented the signing service from approving that release. The process that decides what gets signed also needs protection.
The 3CX incident in March 2023 followed the same pattern. The business telephone software company shipped a maliciously modified desktop application bearing its valid signature. Intruders reached its build environments after an employee installed a compromised trading application from another vendor. One compromised software supplier had become the route into another.
Malicious Dependencies
Modern software incorporates libraries and packages maintained by other people. Those packages can depend on still more packages, so a developer may rely on code several steps removed from the application’s direct dependencies. An attacker who controls a dependency can introduce malicious code into applications that install or build with an affected version.
In 2018, the maintainer of event-stream, a widely used JavaScript package, transferred control to a volunteer who offered to take over. The new maintainer added a dependency that was subsequently modified to steal cryptocurrency wallet information. The malicious code targeted the Copay wallet application, rather than every program that used event-stream.
The XZ Utils backdoor shows how a dependency can become a path into an unrelated service. XZ Utils provides compression tools and a library that some Linux distributions loaded indirectly into their remote login service. An account using the name Jia Tan contributed patches, became a co-maintainer, and introduced a backdoor in early 2024. Malicious code hidden in test files was incorporated during the build. On affected systems, the backdoor allowed an attacker with a particular private key to run commands through the login service.
Andres Freund, a Microsoft developer, discovered the XZ compromise in March 2024 while investigating unusual CPU use and delays in remote logins. The affected versions had reached development releases of Debian and Fedora, but not their stable releases. The dependency’s legitimate maintainer account had distributed the malicious changes.
In September 2025, Shai-Hulud, a self-replicating worm, spread through the npm JavaScript package repository. Code in compromised packages stole credentials that allowed publication to the repository, then used those credentials to place itself in additional packages. Access to a publisher’s account was enough to spread the attack.
These attacks exploit who is allowed to publish a dependency or what is included in its release. A signature from the expected maintainer cannot establish that the maintainer’s account, decisions, or build process are safe.
Protecting the Release Process
Protecting a release requires checks on its inputs, its build, and its signing process. Several defenses address different parts of that work:
-
Reproducible builds produce identical output from the same source and specified build environment. Independent rebuilds can reveal differences between the expected program and the distributed release. They do not establish that the source itself is safe.
-
Signed build records identify the source revision, tools, and inputs used to produce a release. They help an organization check whether the release came through its approved process, provided the records and the process that creates them are trustworthy.
-
A software bill of materials (SBOM) lists a product’s components, helping an organization identify affected products when a vulnerable or compromised dependency is discovered.
-
Public release logs make signed releases visible to outside monitors. Requiring a verifiable log entry before accepting an update makes a secretly targeted release easier to detect.
-
Dependency review limits unnecessary packages, records the exact versions used, and checks changes before accepting updates.
-
Hardware protection can prevent export of a signing key. Access controls must also restrict which releases the signing service will sign, since a stolen key is not required to abuse a legitimate signing service.
Preparing for Quantum Attacks
Protecting keys and build systems cannot compensate for a signature algorithm that an attacker can break. RSA, Diffie-Hellman, and elliptic curve schemes depend on the difficulty of factoring integers or computing discrete logarithms. A sufficiently powerful quantum computer would change the difficulty of those problems.
In 1994, Peter Shor described a quantum algorithm that could solve both problems far more efficiently than the best known classical algorithms. An attacker with a large enough quantum computer could recover RSA or elliptic curve private keys from their public keys and forge signatures. Increasing these key sizes is not a practical long-term solution. Post-quantum cryptography uses constructions intended to resist attacks by quantum computers as well as classical ones.
Symmetric encryption and hashes face a less drastic change. Grover’s algorithm, published in 1996, can reduce an ideal search through \(2^n\) possibilities to roughly \(2^{n/2}\) steps. A 256-bit symmetric key therefore retains about 128 bits of security against this generic search. The same reasoning applies to hash preimage searches. Quantum collision attacks require a separate analysis, but hash functions and hash-based signatures remain useful with appropriate parameters.
The transition matters before such a quantum computer exists. An adversary can record encrypted traffic now and attempt to recover its secrets later. This strategy is called harvest now, decrypt later. Data that must remain confidential for many years needs protection against that future attack. Signatures also need a migration plan, particularly for devices expected to authenticate software updates for many years.
The U.S. National Institute of Standards and Technology (NIST) began a public selection process in 2016 and published its first three post-quantum standards in August 2024:
-
ML-KEM establishes a shared secret for symmetric encryption, serving the role that Diffie-Hellman fills in many protocols.
-
ML-DSA provides digital signatures and is intended for broad use as a replacement for schemes such as RSA and ECDSA.
-
SLH-DSA provides digital signatures built from hash functions. It extends the idea of combining many one-time signing keys under one public key. Its signatures are larger than those of ML-DSA, but it offers an alternative based on different security assumptions.
During migration, protocols can use hybrid key establishment: combine a classical method with a post-quantum method and derive a session key from both results. With a properly designed combination, the shared secret remains protected if either method resists the attack. Migrating signatures also requires updating the software that checks them, including the certificate handling and update mechanisms on existing devices.