Software distribution needs a check that anyone can verify and only the publisher can produce. Public-key cryptography, also called asymmetric cryptography, provides it with a mathematically related pair of keys. The private key remains secret, and the corresponding public key can be distributed freely. In a signature scheme, the private key creates signatures and the public key verifies them. For this to work, recovering the private key or forging a signature from the public key must be computationally infeasible.
The Public-Key Idea
By the 1970s, computer networks were making it possible for people to conduct business without meeting in person. Symmetric cryptography, using a shared key, still required them to arrange a secret key in advance. It also gave both parties the ability to generate authentication tags, so a recipient could check a message’s authenticity but could not use the tag to convince a third party that the other key holder had sent it.
In 1976, Whitfield Diffie and Martin Hellman proposed separating public and private cryptographic operations to address these problems. They described the requirements for public-key encryption and digital signatures and introduced a way to establish a shared secret by exchanging public information. A year later, Ronald Rivest, Adi Shamir, and Leonard Adleman at the Massachusetts Institute of Technology developed a system supporting both encryption and signatures. Their system, RSA, was named for the inventors.
Equivalent methods had already been found in secret at GCHQ, the British signals intelligence agency, between 1969 and 1974, but the work was classified and was not declassified until 1997.
One-Way and Trapdoor Functions
Public key cryptography rests on calculations that are efficient in one direction and infeasible to reverse. A one-way function is easy to evaluate and infeasible to invert. Several appear throughout cryptography:
- Multiplication and factoring.
- Multiplying two large prime numbers is fast. Recovering the primes from the product is not, and no efficient method is known when the primes are several hundred digits long.
- Modular exponentiation and the discrete logarithm.
- Raising a number to a power modulo a large prime is fast. Recovering the exponent from the result is the discrete logarithm problem, for which no efficient method is known.
- Scalar multiplication on an elliptic curve.
- Adding a point on a curve to itself a chosen number of times is fast. Recovering that number from the starting and ending points is believed infeasible.
- A cryptographic hash function.
- Computing a digest is fast, and preimage resistance is the requirement that reversing it is infeasible.
None of these is proven hard. They are believed to be hard because they have resisted concentrated effort for decades, which is the same standard of evidence that supports every cipher in use.
A one-way function on its own is not enough to build a public-key system, because the legitimate key holder also needs to perform the difficult direction. Secret information that makes an otherwise infeasible calculation easy is called a trapdoor, and a one-way function that has one is a trapdoor function.
Factoring is an example. Given \(n = p \times q\) with \(p\) and \(q\) unknown, recovering them is infeasible. Given \(n\) and one of the factors, the other can be found via a single division. Knowledge of one factor is the trapdoor. A hash function has no trapdoor, which is why public key encryption cannot be built from hashing alone. Signatures are a different matter, and we will see a signature scheme later that uses nothing but a hash function.
Public Key Cryptography
Public key cryptography gives each party two mathematically related keys. The pair is generated together, and the relationship between them runs in one direction only. The public key can be computed from the private key. The private key cannot be computed from the public key.
Public and private keys support several operations, each solving a different problem, so the role of a key depends on how it is being used:
| Operation | Who uses which key? | What it accomplishes |
|---|---|---|
| Public-key encryption | Anyone encrypts with the recipient’s public key. The recipient decrypts with the private key. | Confidential delivery to that recipient. |
| Digital signature | The signer signs with the private key. Others verify with the signer’s public key. | Publicly verifiable authentication of a message. |
| Key agreement | Each participant combines private information with the other’s public contribution. | Establishing a shared secret for subsequent symmetric protection. |
Encrypting with a recipient’s public key does not identify the sender, because anyone can use that public key. A signature authenticates the signed message but leaves it readable. Key agreement creates a shared secret, but the participants also need a way to check whom they are sharing it with.
The signature operation performs what a shared secret cannot do. It is asymmetric in a way that’s useful for software distribution: one signer, any number of verifiers, and no secret on any of the verifying machines.
We will cover encryption and key exchange first, because digital signatures use the same key pairs and rely on the same hard problems.
RSA
RSA’s one-way function is modular exponentiation, and knowledge of the modulus’s factors is the trapdoor. Generating a key pair takes five steps:
-
Choose two large random prime numbers, \(p\) and \(q\).
-
Compute the modulus \(n = p \times q\).
-
Compute \(\varphi(n) = (p-1)(q-1)\).
-
Choose a public exponent \(e\) that shares no factor with \(\varphi(n)\). In practice, \(e\) is almost always 65537.
-
Compute the private exponent \(d\), the multiplicative inverse of \(e\) modulo \(\varphi(n)\), so that \(e \times d \equiv 1 \pmod{\varphi(n)}\).
The public key is the pair \((e, n)\) and the private key is \((d, n)\). The two primes must be destroyed or kept as secret as \(d\), since anyone holding either one can divide \(n\) to get the other, compute \(\varphi(n)\), and from it derive \(d\).
Encryption and decryption are both modular exponentiation, and each works on a single number \(P\) smaller than \(n\). A message therefore has to fit in that range, and a longer one would have to be split into blocks of that size. Treating a message as such a number:
\[C = P^{e} \bmod n \qquad P = C^{d} \bmod n\]
The way \(d\) was chosen guarantees that the second operation undoes the first. Computing \(d\) from the public key requires \(\varphi(n)\), which requires the factors of \(n\).
Here’s an example with small numbers:
With \(p = 61\) and \(q = 53\), the modulus is \(n = 3233\) and \(\varphi(n) = 3120\). Choosing \(e = 17\) gives \(d = 2753\). Encrypting \(P = 123\) produces \(123^{17} \bmod 3233 = 855\), and \(855^{2753} \bmod 3233\) returns 123. A modulus of 3233 is factored instantly. A real RSA modulus is at least 2048 bits, a number of about 617 decimal digits. The appendix works through key generation in more detail.
The large size is needed because factoring is far easier than searching. An attacker never has to try candidate private keys one at a time. Algorithms such as the number field sieve exploit the structure of the problem and factor a modulus in far less work than its length suggests, and the work grows slowly as the modulus grows. A 2048-bit modulus is estimated to take about as much effort to factor as a 112-bit symmetric key takes to search, so a key eighteen times longer buys slightly less security. Finding the primes is not the difficulty. Primes remain plentiful at that size, with roughly one in every 355 odd numbers near \(2^{1024}\) being prime, and a key generator finds a pair in well under a second.
Splitting a long message into blocks is not what happens in practice. A sender generates a random symmetric key, encrypts that key with the recipient’s public key, and encrypts the data with the symmetric key. The main reason is speed: modular exponentiation on numbers of this size is thousands of times slower than AES, so RSA is given the smallest job that will do, and the symmetric ciphers we previously covered will carry the data. Other reasons are covered below.
Elliptic Curve Cryptography
RSA keys are large and getting larger, and the arithmetic is slow. In 1985, Neal Koblitz and Victor Miller independently proposed basing public key cryptography on elliptic curves instead.
An elliptic curve is the set of points that satisfy an equation of the form \(y^2 = x^3 + ax + b\). Cryptography uses one of these curves over a finite range of integers rather than over the real numbers, so the picture is a scattering of points rather than a smooth arc. Mathematicians define an addition operation on those points. A line drawn through two points of the curve meets it at a third, and the mirror image of that third point across the horizontal axis is defined to be their sum. Adding a point to itself repeatedly is fast even when the number of repetitions is enormous, and working backward from the result to the number of repetitions is not. Few students have studied elliptic curves, and the arithmetic itself is not something we will use or cover in this class. What you need to take from it is that the operation runs easily in one direction, is believed infeasible to reverse, and rests on a different hard problem than RSA does.
Elliptic-curve cryptography (ECC) calculates a public value from a secret number using arithmetic on the points of a curve. Adding a point \(G\) to itself \(d\) times is called scalar multiplication, written \(Q = dG\), and it can be computed efficiently even for enormous \(d\). Recovering \(d\) from \(G\) and \(Q\) is the elliptic curve discrete logarithm problem. The private key is the number \(d\), and the public key is the point \(Q\).
The advantage of ECC is the key size. The best known attacks against elliptic curves are less effective than the best known attacks against factoring, so the same security needs a much smaller key:
| Security level | RSA modulus | Elliptic curve key |
|---|---|---|
| 112 bits | 2048 bits | 224 bits |
| 128 bits | 3072 bits | 256 bits |
| 256 bits | 15360 bits | 512 bits |
Smaller keys mean less data on the wire, less storage, and faster operations, which is why elliptic curves dominate new deployments and why RSA persists mostly where old software has to keep working.
Diffie-Hellman Key Exchange
The other half of Diffie and Hellman’s 1976 paper is describing a way for two parties to arrive at a shared secret over a channel that an adversary can monitor (like the public Internet, for example).
Each picks a private value and uses it to calculate a public contribution. After exchanging those contributions, each combines its own private value with what arrived, and the calculations are arranged so that both obtain the same result. Neither sends that result across the network.
The arithmetic is short. Alice and Bob carry it out in four steps:
-
They agree on a large prime \(p\) and a base \(g\). Both values are public and may be fixed by the protocol they are using.
-
Each picks a secret value at random: \(a\) for Alice and \(b\) for Bob. Neither value is ever transmitted.
-
Alice sends \(A = g^{a} \bmod p\) and Bob sends \(B = g^{b} \bmod p\).
-
Alice computes \(B^{a} \bmod p\) and Bob computes \(A^{b} \bmod p\). Both results are \(g^{ab} \bmod p\), which becomes the shared secret.
An eavesdropper sees \(p\), \(g\), \(A\), and \(B\). Recovering \(a\) or \(b\) from those values is the discrete logarithm problem. The appendix works through a small example.
Diffie-Hellman is not encryption. Nothing is sent that could be decrypted, and neither party chooses the resulting secret, which falls out of the exchange. It also authenticates nobody, so by itself it does not establish who is at the other end. We will cover how protocols use it, and what they have to add to make it safe, in detail later.
Why Not Encrypt Everything This Way
Public key algorithms can encrypt, so an obvious question is why symmetric ciphers are still used at all. Four reasons rule it out:
-
Speed. Modular exponentiation on 2048-bit numbers and scalar multiplication on a curve are orders of magnitude slower than AES, which processors implement in hardware. Symmetric ciphers handle gigabits per second, and public key operations are counted in thousands per second.
-
Expansion. RSA ciphertext is the size of the modulus, so encrypting a single byte with a 2048-bit key produces 256 bytes. The encoding that makes RSA encryption safe reserves part of each block, leaving room for at most 190 bytes of plaintext, so anything longer has to be split across many blocks. Elliptic curve schemes add a fixed amount of data per message rather than a multiple of it, which is tolerable for a key and wasteful for a stream of packets. Symmetric ciphertext is essentially the same length as its plaintext.
-
Chosen plaintext is free. The encryption key is public, so anyone can encrypt a guess. Used directly, RSA maps a given plaintext to the same ciphertext every time, so an attacker facing a small set of plausible messages encrypts all of them and compares the results against an intercepted ciphertext.
-
Mathematical structure survives encryption. The arithmetic that makes the scheme work also carries relationships from the plaintext into the ciphertext. With RSA used directly, the product of two ciphertexts is the ciphertext of the product of their plaintexts, so an attacker can turn an intercepted message into a predictably related one without knowing either. A block cipher leaves no such relationship, and for this reason and the one above, secure public key encryption applies a randomized encoding to the message before the mathematical operation.
Public key algorithms were built to distribute keys and to sign values, not to carry bulk data. Systems use them for those two jobs and hand the data itself to a symmetric cipher. We will cover how protocols combine the two in detail later.
Signing and Verification
A digital signature is a value produced from a message and a private signing key. Anyone with the signer’s public key, also called the verification key, can check it, and a valid result establishes both that the message is unaltered and that it came from the holder of the private key. The two names describe the only operation each key performs in a signature scheme. Any message can be signed: a contract, an email, a financial transaction, a certificate, a log entry, or a program.
Let’s consider the example of software distribution. The publisher generates a public-private key pair, protects the private key, and uses it to sign each update it publishes. Customers receive the update and its signature, then run a verification algorithm with those two inputs and the publisher’s public key. The result tells them whether the signature is valid for that exact message under that key.
A copy of the update can pass through an untrusted download mirror without giving the mirror the ability to alter it undetectably. To substitute a modified file, the mirror would also need a valid signature for the new contents, and producing one without the private key is computationally infeasible. The publisher must still provide customers with an authentic copy of its public key, but that key can be included in the installed software and used to verify later updates.
Hashing the Message
An update might contain gigabytes of data. Hashing lets a signature scheme process that data efficiently while its more expensive public-key calculation works with the compact hash. The signature remains tied to the entire message through the hash.
This dependence gives collision resistance a direct role in preventing forgery. Suppose an attacker creates two documents with the same digest: one harmless and one containing a fraudulent payment instruction. In a scheme that signs the digest, a signature obtained for the harmless document also verifies for the fraudulent one. The attacker chose both documents, so resistance to replacing a particular existing document is not enough. Finding any usable pair of colliding documents must be infeasible.
Signing is often described as encrypting the digest with the private key. For RSA the picture is close enough to be useful, since the signing operation applies the private exponent to the encoded digest and verification applies the public exponent to recover it. The analogy has limits. RSA prepares the digest with encoding rules of its own, so a signature is not the ciphertext that RSA encryption would produce from the same value, and elliptic curve signature schemes have no corresponding encryption operation, so the analogy does not apply to them. What verification checks in every scheme is a mathematical relationship between the message, the signature, and the public key.
Three signature schemes account for most current use:
-
RSA-PSS, RSA’s Probabilistic Signature Scheme, combines hashing with a randomized encoding that prepares the digest for signing. RSA encryption uses different preparation rules.
-
ECDSA, the elliptic curve digital signature algorithm, appears in TLS certificates, Bitcoin, and code signing.
-
Ed25519 is a more recent elliptic-curve scheme. It is deterministic, deriving its per-signature random value from the message and the key rather than drawing it from a generator, which removes an entire class of implementation failure.
Signatures Built Only From Hash Functions
Digital signatures can be built from hash functions without relying on factoring or discrete logarithms. In 1979, Leslie Lamport described a one-time signature scheme based on one-way functions. The basic idea is that revealing a secret can prove a choice that the signer made.
Consider signing a message containing just one bit:
-
Key generation. Generate two long, random secret values: one for 0 and one for 1. These values form the private key. Hash each value and publish the two digests, labeled 0 and 1, as the public key.
-
Signing. Reveal the secret corresponding to the message bit. To sign 0, reveal the secret for 0; to sign 1, reveal the secret for 1. The revealed value is the signature.
-
Verification. Hash the revealed value and compare it with the public digest labeled with the message bit. A match verifies the signature.
Each possible bit value has its own secret. After seeing a signature for 0, an attacker knows the secret for 0 but still lacks the secret needed to sign 1. Preimage resistance makes finding that missing secret from its published digest computationally infeasible.
To sign a longer message, first hash it with a collision-resistant hash function. Use a separate pair of secrets for every position in the digest, revealing one secret from each pair. A 256-bit digest therefore requires 256 pairs of secrets, and its signature contains 256 revealed values.
There are two limitations to this scheme: (1) the keys and signatures are large, and (2) each key pair should sign only one message. Signing a second message with the same key reveals both secrets wherever the two digests differ, and an attacker can then combine previously revealed secrets to attempt forgeries.
Ralph Merkle showed how to combine many one-time signing keys under a single public key, using a fresh signing key for each message. This idea underlies one of the post-quantum signature schemes we will discuss later.
What a Signature Establishes
Because a recipient can verify a signature without being able to create one, the signed message can serve as evidence to others. With a MAC, the recipient could have generated the tag. A signature removes that ambiguity and supports non-repudiation: evidence against a later denial that the holder of a signing key signed a message.
The evidence depends on how the key was protected. Anyone who steals the private key can produce valid signatures, and verification cannot reveal who was at the keyboard or what they intended. Connecting a signature to a person therefore also depends on identity checks and records of key use.
A signature also leaves the truth and safety of the message for the recipient to judge. Galileo’s anagram could preserve an incorrect astronomical claim, and a software signature can authenticate a program with a serious vulnerability. The signature establishes a connection between particular bytes and a signing key.
That leaves the question the next section answers. A verifier holding a public key and a valid signature knows only that the two match, and an attacker can generate a key pair as easily as anyone else. Accepting those bytes as a trusted software update requires knowing whose key it is.