Encryption from Chapter 9 lets you send secrets. But it does not prove who sent them. Anyone with Bob's public key can encrypt a message pretending to be Alice. Digital signatures solve this: the signer's private key creates a proof that anyone with the public key can verify, but nobody can forge.
Encryption ensures only the intended recipient can read a message. But it says nothing about the sender. Alice can encrypt a message to Bob, and so can Eve. Bob has no way to tell them apart.
Asymmetric encryption from Chapter 9 provides confidentiality. Bob decrypts a message and reads it. But nothing in the ciphertext proves Alice wrote it. Eve could have encrypted the same message with Bob's public key, and Bob would have no way to distinguish the two.
MACs from Chapter 3 solved the authentication problem for shared-key settings. If Alice and Bob share a secret key, a MAC proves the message came from someone who knows that key. But MACs have a fundamental limitation: both sides hold the same secret. Both can create and verify tags. There is no way for a third party to confirm who actually authored the message.
Digital signatures use asymmetric keys to solve this. Only the signer can create a signature (private key), but anyone can verify it (public key). If Alice signs a contract, Bob can prove to Charlie that Alice signed it. Alice cannot deny having signed it, because only her private key could have produced that signature.
This property is called non-repudiation. It is something MACs cannot provide, because both parties hold the shared key. With MACs, Bob could have forged the tag himself. With signatures, only Alice's private key could have produced the proof.
Signatures are the mirror image of encryption. In encryption, the public key locks and the private key unlocks. In signatures, the private key signs and the public key verifies. Same key pair, opposite directions.
A signature is a value computed from a message and a private key. Anyone with the corresponding public key can verify the signature is genuine. No one without the private key can produce a valid signature.
Only Alice has her private key. The signature she produces is mathematically bound to both the message and her key. Nobody else can create it.
Bob, Charlie, anyone can verify Alice's signature using her public key. The verification is a mathematical check, not a secret.
Change even one bit of the message, and the signature no longer verifies. Signatures bind the signer's identity to the exact content.
Signatures give you two guarantees at once: authentication (the signer has the private key) and integrity (the message has not been modified). Combined with encryption, you get confidentiality, integrity, and authentication.
RSA signatures operate on numbers smaller than the modulus. A real message might be megabytes. The solution: hash the message first, then sign the fixed-length digest.
RSA can only operate on values smaller than (typically 256 bytes for a 2048-bit key). You cannot sign a 10 MB file directly. Even for elliptic curve schemes, the input must be a fixed-size scalar.
The solution is the hash-then-sign paradigm. Hash the message with SHA-256 to get a 32-byte digest. Sign the digest. To verify: hash the received message, then check the signature against that hash. If the signature matches, the message is authentic.
Because the hash function is collision-resistant (Chapter 2), finding a different message with the same hash is infeasible. A signature on the hash is as good as a signature on the full message.
Watch the two-step process: first hash the message to a fixed-length digest, then sign the digest.
RSA signatures use the same math as RSA encryption, but in reverse. The private key exponent signs, the public key exponent verifies. Walk through the process with small numbers.
The signer raises the hash to the private exponent . The verifier raises the signature to the public exponent . If the result equals the hash, the signature is valid. This works because of the same RSA identity from Chapter 9:
Walk through RSA signing step by step. Choose primes, build a key pair, sign a number, and verify the signature.
Just like RSA encryption, textbook RSA signatures need padding to be secure. RSASSA-PKCS#1 v1.5 adds deterministic padding. RSA-PSS adds randomized padding for stronger security guarantees. Never implement textbook RSA signatures in production.
The demo above used tiny primes. Real RSA signatures use 2048-bit keys and PSS padding. Try signing a message with the Web Crypto API, then modify it and watch verification fail.
RSA-PSS includes random salt in the padding. The same message produces a different signature each time, preventing certain attacks on deterministic schemes.
An RSA-2048 signature is always 256 bytes. An RSA-4096 signature is 512 bytes. The signature size depends only on the key, not on the message.
Sign a message with RSA-PSS 2048-bit. Then modify the received message and try to verify. Any change invalidates the signature.
Elliptic Curve Digital Signature Algorithm uses the same curve math from Chapter 8. A P-256 signature is 64 bytes instead of 256 for RSA-2048, with equivalent security. ECDSA powers most TLS certificates today.
The signer has a private key scalar and a public key point . To sign a message:
1. Hash the message:
2. Pick a random per-signature nonce
3. Compute the curve point , take
4. Compute
5. The signature is the pair
If the per-signature nonce is reused or predictable, the private key can be recovered. This is exactly what happened to Sony's PlayStation 3 ECDSA implementation in 2010: they used the same for every signature, and hackers extracted the private key from two signatures.
The math is straightforward. Given two signatures and on different messages (same because same ):
Once is known, recovering the private key is just arithmetic. A single reused nonce compromises the key forever.
ECDSA is the most widely deployed signature algorithm. Bitcoin uses it (secp256k1). TLS certificates use it (P-256). But its reliance on a random nonce per signature is a source of implementation risk. This is the problem Schnorr and EdDSA solve.
The Schnorr signature scheme is the simplest discrete-log-based signature. Ed25519 is its modern instantiation on Curve25519, with deterministic nonces that eliminate the ECDSA nonce problem entirely.
Alice has private key and public key . To sign a message :
Pick a random nonce , compute the commitment point .
Hash the commitment, public key, and message together: .
Compute . The signature is .
Verification works because .
The response equation is linear. This seemingly simple property has profound consequences. If Alice and Bob both produce Schnorr signatures on the same message, their signatures can be added together to form a single valid multi-signature. The combined signature is the same size as a single one.
This linearity makes multi-signatures, threshold signatures, and adaptor signatures possible. ECDSA does not have this property because its equation involves , which breaks linearity.
Ed25519 is a Schnorr signature scheme instantiated on Curve25519 (in twisted Edwards form). Its critical improvement over classical Schnorr: the nonce is derived deterministically as a hash of the private key and message, not picked randomly.
No random number generator is involved in signing. Different messages produce different nonces by construction. Nonce reuse is impossible.
Deterministic: No RNG in signing. No nonce-reuse risk.
Faster: Edwards curves allow constant-time arithmetic optimized for speed.
Simpler: Fewer implementation choices, fewer ways to get it wrong.
Smaller: 32-byte keys vs 33-byte compressed ECDSA keys.
The same message, three algorithms. Compare key sizes, signature sizes, and speed.
Schnorr patented his scheme in 1989 (US Patent 4,995,082). The patent expired in 2008. During those 19 years, ECDSA was designed specifically to work around the patent. After it expired, Dan Bernstein designed Ed25519 (2011) for Curve25519, optimized for security, performance, and resistance to side-channel attacks. It has since become the recommended signature scheme for new systems, and powers Bitcoin's Taproot (BIP-340) and many modern protocols.
Digital signature schemes are mathematically sound. But implementation mistakes, nonce reuse, and malleability can break them in practice.
Given a valid ECDSA signature , the pair is also a valid signature on the same message. This does not break authentication, but it can break systems that use the signature as a unique identifier.
Bitcoin experienced this firsthand. Before the SegWit upgrade, transaction IDs were computed from the full transaction including the signature. An attacker could take a valid transaction, replace with , and create a different transaction ID for the same payment. This “transaction malleability” caused real losses.
A signed message arrives. Try these attacks and see what happens.
Ed25519 solves the nonce-reuse problem by design. RSA-PSS is resistant to malleability. When choosing a signature algorithm, the question is not just “is the math secure?” but “how hard is it to use correctly?”
Digital signatures are one of the most widely deployed cryptographic primitives. Every HTTPS connection, every software update, every cryptocurrency transaction relies on them.
TLS certificates. Every HTTPS certificate is signed by a certificate authority. Your browser verifies the CA's signature to trust the server's public key. This chain of trust is the subject of Chapter 11.
Code signing. Operating systems verify cryptographic signatures on software updates and applications. Apple, Microsoft, and Linux distributions all sign their packages. An unsigned or incorrectly signed binary is rejected.
Git commits. Git supports GPG and SSH signatures on commits and tags. GitHub shows a “Verified” badge on signed commits. This proves the commit was created by the key holder.
JWT (JSON Web Tokens). JWTs used in web authentication are signed with HMAC (symmetric) or RSA/ECDSA (asymmetric). The signature ensures the token has not been tampered with and was issued by the expected server.
Blockchain. Every Bitcoin or Ethereum transaction is signed with the sender's private key. The network verifies the signature before accepting the transaction. No valid signature, no transfer.
Digital signatures appear in protocols you use every day. Examine their structure.
{
"alg": "ES256",
"typ": "JWT"
}{
"sub": "alice@example.com",
"iat": 1711929600,
"exp": 1712016000,
"role": ""
}Digital signatures are powerful but require careful implementation. These guidelines reflect how modern systems use them safely.
Ed25519 is faster, has smaller signatures, and eliminates nonce-reuse risk through deterministic signing. Unless you need compatibility with existing ECDSA systems, Ed25519 is the default choice for new projects.
Never sign raw messages. Always hash the message with SHA-256 (or the hash built into the scheme) before signing. This is handled automatically by Web Crypto and all reputable libraries, but matters if you build from primitives.
RSA-PSS with SHA-256 is the recommended RSA signature padding. PKCS#1 v1.5 signatures are still widely used and not broken the way PKCS#1 v1.5 encryption padding is, but PSS provides stronger security proofs.
A single reused nonce in ECDSA leaks the private key. Use a cryptographically secure random number generator, or better yet, use EdDSA which derives nonces deterministically and cannot suffer from this attack.
Digital signatures solve the authentication problem for public-key cryptography. But one question remains: how do you know the public key you are verifying against actually belongs to Alice and not Eve? That is the problem of trust and public key infrastructure, the subject of Chapter 11.
This chapter introduced digital signatures: the ability to prove authorship of a message using a private key, in a way that anyone with the public key can verify. Combined with encryption from Chapter 9, you now have confidentiality, integrity, and authentication.
Digital signatures solve the authentication problem. The private key creates a proof that anyone with the public key can verify, but nobody can forge. Unlike MACs, signatures provide non-repudiation.
Hash-then-sign makes signatures practical. Hash the message to a fixed-size digest, sign the digest. The collision resistance of the hash function guarantees this is as secure as signing the full message.
RSA signatures were the first practical scheme. Sign with private exponent , verify with public exponent . PSS padding provides the strongest security guarantees.
ECDSA provides equivalent security with much smaller signatures (64 bytes vs 256 bytes for RSA-2048). It powers most TLS certificates and blockchain transactions. But it requires a fresh random nonce per signature, and nonce reuse is catastrophic.
Schnorr signatures are the simplest discrete-log scheme. Their linear structure enables multi-signatures. Ed25519 is Schnorr on Curve25519, with deterministic nonces that eliminate the most dangerous implementation pitfall. Faster, simpler, and harder to misuse than ECDSA. The recommended choice for new systems.
You can now sign and verify messages. But verification only works if you trust the public key. How do you know a public key belongs to Alice and not to an attacker? Binding identities to public keys through certificates and chains of trust is the subject of Chapter 11.