RSA

Table of Contents

1. Cryptography

Alice wishes to send a message (represented as numbers) to Bob securely (which means that nobody else can read it). Eve is a malicious eavesdropper who can monitor network traffic. A secure cryptographic system would prevent Eve from reading (decoding) the encrypted message that Alice sends to Bob.

In classical cryptography, Alice and Bob must share a secret “codebook” in advance, and use that shared knowledge to encode and decode messages they send to each other. However, these encryption methods suffer from the “key distribution problem.” As the RSA paper explains, “the problem is that before a private communication can begin, another private transaction is necessary.” Typically, this is done using a private courier of sorts, but this increases the risk of the codebook leaking or, in cases such as an electronic mail system, it is infeasible.

In public-key cryptography, however, private couriers are not needed. In this system, Bob publishes publicly a public key \(K\), and keeps secret a private key \(P\). This system allows Alice to encrypt messages using the public key \(K\), but only the private key \(P\) can decrypt it. In other words, anyone can send encrypted messages to Bob using \(K\), but only Bob can decrypt the messages using his corresponding private key \(P\).

Observe that in this system, no private transactions between Alice and Bob are needed to establish encrypted communication. This is because the only thing needed to encrypt messages are things that can be publicly known.

2. RSA

RSA (Rivest-Shamir-Adleman) is a public-key cryptosystem. First, Bob must generate a public-private key pair. To do so, Bob:

  1. Chooses two large primes (e.g. 1024 bits) \(p, q\) and an integer \(e\) coprime to \((p-1)(q-1)\).
  2. Publishes the public key \((N, e)\) where \(N=pq\).
  3. Retains the private key \((N, d)\) where \(d = e^{-1} \pmod{(p-1)(q-1)}\).

Now Alice, to send a message \(x\) (an integer modulo \(N\)) to Bob:

  1. Computes \(E(x) = x^e \text{ mod } N\).
  2. Sends \(y=E(x)\) to Bob.

Bob finally decrypts it using his private key:

  1. \(x=D(y) = y^d \text{ mod } N\).

However, to show that the above procedures works and is secure, we need to know that it is correct, is is secure, and that it is efficient.

2.1. Correctness

Proving correctness comes down to proving that \(D(E(x)) = x \; \forall x \in \{0, 1, \dots, N-1\}\).

Proof: Recall that \(E(x) = x^e \text{ mod } N\) and \(D(x) = y^d \text{ mod }N\) where \(y=x^e\). Also, \(d=e^{-1} \pmod{(p-1)(q-1)}\). So, it is equivalent to prove that \(x^{ed} \equiv x \pmod{N}\).

Equivalently, we have \(x(x^{ed-1} - 1) \equiv 0 \pmod{N}\). So, it is sufficient to prove that \(p | x(x^{ed-1}-1)\) and \(q | x(x^{ed-1}-1)\).

Note that \(ed = k(p-1)(q-1)+1\) for some \(k\in\mathbb{Z}\). Thus, \(ed-1 = k(p-1)(q-1)\). In other words, we now want to prove that \(p | x(x^{k(p-1)(q-1)}-1)\) and \(q | x(x^{k(p-1)(q-1)}-1)\).

If \(p|x\), then we are done. Otherwise, we need to prove that \(p | x^{k(p-1)(q-1)}-1\). Since we know that \(\text{gcd}(p,x)=1\), we know by Fermat’s Little Theorem that \(x^{p-1} \equiv 1 \pmod{p}\) for any prime \(p\). Then:

\begin{align} x^{k(p-1)(q-1)}-1 \equiv \left(x^{p-1}\right)^{k(q-1)}-1 \equiv 1-1 \equiv 0 \pmod{p} \notag \end{align}

Thus, \(p|x^{k(p-1)(q-1)}-1\). We can use the same argument to show the same for \(q\), and we are done. \(\square\)

Alternate Proof (Rivest-Shamir-Adleman): Recall that Euler’s Theorem states that \(x^{\phi (m)} \equiv 1 \pmod{m}\) for all \(x\) such that \(m\) and \(x\) are coprime. Then, when \(m=N=pq\), we have \(\phi(N)=pq-p-q+1 = (p-1)(q-1)\). This is because the only numbers less than \(N\) that are not coprime to \(N\) are the multiples of \(p\) and the multiples of \(q\).

Thus, by Euler’s Theorem, we have:

\begin{align} x^{ed} \equiv x^{k(p-1)(q-1)+1} \equiv \left(x^{(p-1)(q-1)}\right)^kx\equiv x \pmod{N} \notag \end{align}

For the special case \(x\) where \(x\) and \(N\) are not coprime, then we have \(p|x\) and \(q|x\) as before and it is true. \(\square\)

2.2. Security

We want to argue that Eve learns nothing about the message \(x\) by observing \(E(x), N, e\). There are several approaches that Eve can take, but we can show that each of these is not a problem:

  1. Eve can try guessing \(x\). However, if we are working with \(1024\) bit numbers, there are \(2^{1024} \approx 10^{308}\) possibilities for \(x\), which is clearly not feasible.
  2. Eve can try to figure out the factors \(p\) and \(q\). However, there is no known way to efficiently factor \(N\), especially when \(N\) is very large.
  3. Eve can try to solve the equation \(x^e \equiv y \pmod{N}\) for \(x\). However, this is equivalent to the discrete log problem, which is known to be very hard.

In other words, it is realistically infeasible (basically impossible) for these attacks to succeed due to the amount of computation required to calculate any of these values from what is publicly known. However, a theoretical quantum computer can efficiently factorize large numbers.° This has led to a new field of post-quantum cryptography.

2.3. Efficiency

Efficiency of the algorithm comes down to two main parts: computing \(e, d, E(x), D(y)\), and choosing the large primes in order to compute those.

  1. Computing \(e, d, E(x), D(y)\): for \(e\), we can trivially choose anything coprime to \((p-1)(q-1)\) (often this is \(2^{16} +1\), which is prime). For \(d\), we can use extended Euclid to find the inverse of \(e\). Finally, for \(E(x)\) and \(D(y)\), we can efficiently calculate these via repeated squaring.
  2. Choosing large primes: The following algorithm works to choose a large prime. First, we pick a random \(1024\) bit number. Test to see if the number is prime; if it is, we are done, and if it isn’t, we just try again. We can see that this is efficient because the Prime Number Theorem tells us that on average, \(1\) in every \(\text{ln }m\) numbers is prime.

2.3.1. Primality Testing

This leaves us with the question of how we test if a large number is prime. The naive method would be to try every integer up to \(\sqrt{n}\) to see if it divides \(n\), but the running time of this is way too high for large \(n\). Better is the Fermat test:

ALGORITHM Fermat(n)
CHOOSE a FROM {2, 3, ..., n-1} AT RANDOM
IF gcd(a, n) != 1
    OUTPUT "not prime"
ELSE IF a ** (n - 1) != 1 (mod n)
    OUTPUT "not prime"
ELSE
    OUTPUT "prime"

If \(n\) is prime, the above algorithm is always correct.

However, if \(n\) is not prime, the algorithm may output a wrong answer! This happens when the chosen \(a\) is not a witness, i.e. \(gcd(a, n) = 1\) and \(a^{n-1} \equiv 1 \pmod{n}\) even when \(n\) is not prime.

The good news is, however, for almost all inputs \(n\), at least half of the \(a\) are witnesses. This means that if we repeat the test \(100\) times, the correct probability that the answer is correct becomes \(\geq 1-\frac{1}{2^{100}}\). This means that it is more likely for the computer to suffer a hardware failure while computing than to get the wrong answer. There are, however, inputs \(n\) that always fail the test: these are called Carmichael numbers, and they have no witnesses \(a\). Fortunately, real-world implementations do use tests that also work for Carmichael numbers.

Last modified: 2026-02-17 16:31