pk.org: Computer Security/Lecture Notes

Part 3 - Public Keys and Digital Signatures

Letting everyone verify a message while keeping signing private

Paul Krzyzanowski – 2026-09-21

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:

  1. Choose two large random prime numbers, \(p\) and \(q\).

  2. Compute the modulus \(n = p \times q\).

  3. Compute \(\varphi(n) = (p-1)(q-1)\).

  4. Choose a public exponent \(e\) that shares no factor with \(\varphi(n)\). In practice, \(e\) is almost always 65537.

  5. 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:

  1. 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.

  2. Each picks a secret value at random: \(a\) for Alice and \(b\) for Bob. Neither value is ever transmitted.

  3. Alice sends \(A = g^{a} \bmod p\) and Bob sends \(B = g^{b} \bmod p\).

  4. 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:

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:

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:

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.


Next: Part 4: Trusting Keys and Signed Software