Skip to content
pwnsy
cryptographybeginner#digital-signatures#cryptography#public-key#authentication#non-repudiation

How Digital Signatures Work: Signing & Verifying

Digital signatures prove who sent a message and that it is unchanged. How hash-then-sign works, why signing differs from encryption, and verifying.

When you install a software update, connect to a website, or receive a signed email, something is checking that the thing came from who it claims and arrived unchanged. That check is a digital signature. It is one of the most useful ideas in public-key cryptography, and once the mechanics are clear it stops feeling like magic.

A digital signature is a value, computed from a message and a private key, that anyone can verify using the matching public key. A valid signature tells the verifier two things at once. The message was produced by the holder of the private key, and it has not changed since it was signed. NIST specifies the approved algorithms in FIPS 186-5.

Signing is a different job from encryption

People often assume signing is just encryption run backwards. The confusion is worth clearing up, because the goals are opposite.

Encryption is about confidentiality. You scramble a message so only the intended recipient can read it. A signature does the reverse of confidentiality: it leaves the message fully readable and attaches proof of who produced it and that it is intact. You can sign a public announcement that has no secrets in it at all, and the signature still does useful work.

The key roles also flip.

OperationKey used to produceKey used to checkGoal
Public-key encryptionRecipient public keyRecipient private keyConfidentiality
Digital signatureSigner private keySigner public keyAuthenticity and integrity

In encryption, anyone can encrypt to you with your public key and only you can decrypt with your private key. In signing, only you can sign with your private key and anyone can verify with your public key. The private key is always the secret that only its owner holds; what changes is which direction the operation flows.

Hash-then-sign: how it actually runs

Public-key operations are slow and work on inputs of a bounded size. Signing a large file directly would be impractical. So every real scheme signs a hash of the message instead.

The signing process:

  1. Compute a cryptographic hash of the message, for example SHA-256(message), producing a short fixed-length digest.
  2. Apply the signing operation, using the private key, to that digest.
  3. The result is the signature. Send it alongside the original message.

The verification process, run by anyone with the public key:

  1. Recompute the hash of the received message with the same hash function.
  2. Apply the verification operation, using the public key and the signature.
  3. Check that the value derived from the signature matches the freshly computed hash.

If the message changed by even one bit, the recomputed hash differs and verification fails. If the signature was produced by any key other than the matching private key, verification fails. Only the genuine pair of an untampered message and a signature from the right private key passes.

Why hash first

Hashing before signing does two things. It shrinks any input to a fixed size the signing math can handle, and it means the expensive public-key operation runs once over a small digest rather than over megabytes of data. The security of the whole scheme then depends on the hash being collision resistant, which is why modern signatures pair with SHA-256 or stronger.

The algorithms you will meet

Different math underpins different signature schemes, but the sign-with-private, verify-with-public shape is common to all of them.

  • RSA signatures rely on the difficulty of factoring large numbers. Widely deployed and well understood. See How RSA Works.
  • ECDSA and EdDSA use elliptic curves to get equivalent security with much smaller keys and signatures, which is why they dominate new deployments. See How Elliptic-Curve Cryptography Works.

Smaller keys and faster operations have pushed most new systems, including TLS and modern SSH, toward the elliptic-curve schemes. The choice of algorithm changes the performance and key sizes, and leaves the meaning of a valid signature unchanged.

Non-repudiation, and what it needs to hold

Because only the signer possesses the private key, a valid signature is evidence that the signer, and no one else, produced the message. The signer cannot later claim someone else did it, at least not without admitting the key was compromised. This property is non-repudiation, and it is the feature that makes digital signatures legally and operationally meaningful for contracts, audit logs, and software releases.

This is where signatures separate cleanly from HMAC. HMAC also proves integrity and authenticity, but both parties share the same secret key, so either could have produced a given tag. A signature binds a message to one specific private key that only one party holds. See What Is HMAC for the symmetric counterpart.

Non-repudiation only holds under two conditions. The private key stayed private, and the verifier trusts that the public key really belongs to the claimed signer. That second condition is not automatic.

The trust gap: verifying the key itself

A signature proves a message came from whoever controls a given private key. It says nothing about who that is. If an attacker hands you their own public key while claiming it is your bank's, they can sign forgeries that verify perfectly against the key you were given.

Closing this gap is the job of Public Key Infrastructure. Certificates bind a public key to an identity, and a chain of trust leads back to a certificate authority your system already trusts. See What Is PKI. This is exactly the machinery that lets your browser trust a website's key and that lets your operating system trust a software vendor's key. See Code Signing Explained.

Common mistakes

  1. Trusting a signature without validating the key. A valid signature against an unverified key proves nothing about identity. Always check the certificate chain and its revocation status.
  2. Forgetting to check the signature covers what you think. Sign and verify the exact bytes that matter. Data outside the signed region is unprotected, a mistake that has broken real document and token formats.
  3. Reusing randomness in ECDSA. ECDSA needs a fresh, secret random value per signature. Repeat it and an attacker can recover the private key from two signatures. EdDSA avoids this by deriving the value deterministically.
  4. Signing user-supplied data blindly. A signing service that will sign anything can be turned into a forgery oracle. Constrain what your key will sign.
  5. Ignoring key expiry and revocation. A signature valid at signing time may need a trusted timestamp to stay meaningful after the certificate expires.
A signature is only as trustworthy as the key

The most common real-world signature failure is not broken math. It is trusting the wrong public key, or failing to check that a signing certificate has been revoked. Verify the chain, check revocation, and confirm the signed data is the data you care about.

Signature verification failures and certificate-trust weaknesses show up regularly in security advisories. Our Exploit Intelligence dashboard plots live CVEs by severity and exploitation likelihood, so you can see which of these flaws are under active pressure.

Where digital signatures do their work

The same mechanism sits under a wide range of everyday trust decisions, and seeing the spread makes the abstract idea concrete.

Software distribution relies on signatures so that an operating system or package manager can confirm an update came from the expected vendor and was not tampered with in transit or on a mirror. The vendor signs releases, and the client verifies against a key it already trusts. This is the machinery covered in Code Signing Explained.

Transport security uses signatures during the TLS handshake. The server proves control of its private key by signing handshake data, and the browser checks that signature against the public key in the server's certificate, which in turn chains to a trusted authority. That is one of the checks that lets your browser trust a site's key.

Authentication tokens and documents carry signatures so a recipient can confirm the issuer produced them and the contents were not altered. A token signed by an identity provider, or a signed document, verifies against the issuer's public key. Here the earlier warning about signatures covering the exact bytes that matter is especially relevant, because token and document formats have been broken when data outside the signed region was trusted.

Secure messaging and signed email attach a signature so a reader can confirm the sender and integrity of a message even though the message itself may be in the clear. The signature does its work whether or not the content is also encrypted, which is the practical proof that signing and encryption are separate jobs.

A worked example: signing and verifying a release

Follow one file through the full cycle to see where each piece fits. A developer wants to publish a program so that anyone downloading it can confirm it came from them and arrived unchanged.

At signing time, the developer computes a cryptographic hash of the file, for example a SHA-256 digest, which reduces the whole program to a short fixed-length value. They then apply the signing operation with their private key to that digest. The output is the signature. They publish three things: the program, the signature, and, through a certificate, the public key that matches the private key they signed with.

At verification time, a user downloads the program and the signature. Their software recomputes the SHA-256 digest of the file it received. Separately, it applies the verification operation using the developer's public key and the signature, which yields the digest that was signed. The software compares the two digests. If they match, the file has not changed since it was signed and the signature was produced by the matching private key. If they differ by even one bit, verification fails.

Notice what each step proves. The hash comparison proves integrity, that the received bytes are the signed bytes. The public-key verification proves the signature came from the holder of the private key, which is authenticity. Together, and given that only the developer holds the private key, they give non-repudiation, the developer cannot later deny producing the release. What none of it proves on its own is that the public key really belongs to the developer, which is the separate job of trusting the key.

Detection signals: when to distrust a signature

A green check mark is not the end of the story. These are the concrete conditions under which a signature should not be trusted even though the math might verify.

  • The key is unverified. Verification succeeded against a public key you never confirmed belongs to the claimed signer. A signature proves control of a key, and nothing about identity, so an unverified key means an unproven signer.
  • The certificate chain does not lead to a trusted root. If the certificate binding the key to an identity does not chain to an authority your system trusts, the identity claim is unsupported. A self-signed or unknown-issuer certificate carries no external assurance.
  • The certificate is revoked or expired. A key can be withdrawn before its certificate's natural expiry, through revocation. A signature verified against a revoked certificate, or one that expired without a trusted timestamp to fix the signing time, should not be trusted.
  • The signature does not cover the bytes that matter. Some formats sign only part of a document or token. Data outside the signed region is unprotected, and a signature that leaves the meaningful content unsigned proves nothing about that content.
  • The algorithm or hash is weak. A signature using a broken hash or a deprecated scheme can be forgeable in ways a valid-looking check will not reveal. The strength of the hash and the signature algorithm is part of whether the result means anything.
  • The signing context is uncontrolled. A signing service that will sign arbitrary input can be turned into a forgery oracle. A valid signature produced by such a service does not imply the signer endorsed the specific message.
Verification answers two separate questions

A signature check really answers two questions that are easy to blur into one. First, was this exact data signed by the private key that matches this public key? That is what the cryptographic verification proves. Second, does this public key actually belong to the party I think it does? That is a trust question the math never touches, and it is answered by certificates and a chain to an authority you already trust. A confident yes to the first with an unexamined second is the most common way signature-based trust fails.

Several primitives provide overlapping guarantees. Seeing them side by side clarifies what only a signature gives.

MechanismKeysIntegrityAuthenticityNon-repudiation
Digital signaturePrivate to sign, public to verifyYesYesYes
HMACOne shared secretYesYes, to holders of the secretNo
Plain hashNoneDetects accidental change onlyNoNo
Public-key encryptionPublic to encrypt, private to decryptNo, on its ownNo, on its ownNo

A plain hash detects accidental corruption and offers no protection against a deliberate change, since an attacker who alters the message can recompute the hash. HMAC adds a shared secret, so a correct tag proves the message came from someone who knew the secret and was not altered, and because both parties share that secret, either could have produced any given tag, which is why HMAC cannot give non-repudiation. A digital signature uses a private key that only one party holds, so a valid signature points to that one holder, which is what makes non-repudiation possible. Encryption is a different goal entirely, confidentiality, and provides none of these integrity or origin guarantees by itself.

What a signature does not protect

Being precise about the limits keeps signatures from being trusted for jobs they cannot do.

A signature does not keep the message secret. It leaves the content fully readable and only adds proof of origin and integrity. If confidentiality matters, the message must also be encrypted, which is a separate operation with a separate key.

A signature does not prove freshness on its own. A valid signature over an old message is still valid, so a captured signed message can be replayed later unless the protocol adds a nonce, a timestamp, or a sequence number that the verifier checks. Integrity and origin are not the same as recency.

A signature does not establish identity by itself. It proves control of a private key, and connecting that key to a real party is the job of certificates and a trust chain. Without that binding, a verified signature tells you only that some consistent key produced the message.

A signature does not protect data it does not cover. If a format signs part of a document or token and leaves the rest unsigned, the unsigned part carries no assurance. Confirm that the signature spans exactly the bytes whose integrity you rely on.

How it evolved

The idea that a private operation could be verified by a public one made signatures possible in the first place, and early schemes signed messages directly with the public-key operation. Two practical pressures shaped what deployments look like today.

The first was performance and input size. Public-key operations are slow and work on bounded inputs, so signing large files directly was impractical. Hash-then-sign became universal: compute a fixed-length digest, then sign the digest. This made the expensive operation run once over a small value and tied the scheme's security to the collision resistance of the hash, which is why weak hashes have retired signature schemes over time.

The second was key and signature size. The earliest widely deployed scheme, based on the difficulty of factoring, needs large keys for strong security. Elliptic-curve schemes reach equivalent strength with much smaller keys and signatures, so newer systems, including modern TLS and SSH, have moved toward them. The meaning of a valid signature did not change across this shift; the performance and size did. The other long arc has been in trust management, the certificates, chains, revocation, and transparency mechanisms that answer whether a public key belongs to who it claims, which is where most real-world signature failures now live rather than in the underlying math.

Frequently asked questions

Is signing the same as encryption run backwards? No. Encryption provides confidentiality by hiding content, and a signature leaves the message readable while adding proof of origin and integrity. The keys also play opposite roles: you sign with the private key and verify with the public key, the reverse of encrypting to someone with their public key.

Why sign a hash instead of the whole message? Public-key operations are slow and handle only bounded inputs, so signing a large file directly is impractical. Hashing first shrinks any input to a fixed-length digest, so the expensive operation runs once over a small value. The scheme's security then rests on the hash being collision resistant, which is why modern signatures pair with SHA-256 or stronger.

What does non-repudiation actually require? Two conditions. The private key must have stayed private, and the verifier must trust that the public key genuinely belongs to the claimed signer. If either fails, the signer can plausibly deny the signature, so non-repudiation is a property of the whole system, not of the math alone.

How is a signature different from HMAC? HMAC uses one shared secret, so both parties can produce a valid tag, which gives integrity and authenticity but not non-repudiation. A signature uses a private key only one party holds, so a valid signature points to that single holder, which is what enables non-repudiation.

Does a valid signature prove who the signer is? No. It proves the message came from whoever controls the matching private key, and it says nothing about who that is. Binding a key to an identity is the job of Public Key Infrastructure: certificates and a chain of trust to an authority your system already trusts.

Why is reusing randomness in ECDSA dangerous? ECDSA needs a fresh, secret random value for each signature. Reusing it across two signatures lets an attacker recover the private key from those signatures. EdDSA sidesteps the risk by deriving that value deterministically, which removes the chance of a repeat.

What happens to a signature after the certificate expires? Without extra measures, its trust becomes questionable, since the certificate that vouched for the key is no longer valid. A trusted timestamp recorded at signing time fixes when the signature was made, so it can remain meaningful for data signed while the certificate was valid.

Does a valid signature prove the message is recent? No. A signature over an old message stays valid, so a captured signed message can be replayed unless the surrounding protocol adds a nonce, timestamp, or sequence number that the verifier checks. Freshness is a separate guarantee that the signature alone does not provide.

If a signing key is compromised, what happens to past signatures? Signatures made before the compromise can no longer be trusted with confidence, because the attacker could have produced signatures too. Revoking the key and, where available, trusted timestamps that fix the signing time help separate genuine earlier signatures from forgeries, which is why revocation and timestamping matter as much as the signing itself.

Digital signatures give you three things a plain message cannot: proof of origin, proof of integrity, and an origin claim the signer cannot later deny. Pair them with a sound way to trust public keys, handle the private key with care, and they become the backbone of authenticity across the internet.

Sources & further reading

Sharetwitterlinkedin

Related guides