RSA Timing Attack: Recovering a Key From Response Latency

RSA Timing Attack: Recovering a Key From Response Latency

Written by

in

An rsa timing attack recovers a private key by measuring how long the private operation takes, not by breaking any math. The decryption or signing step runs a modular exponentiation with the secret exponent, and the time that exponentiation takes depends on the bits of the key. Feed the server many ciphertexts, measure the latency of each response with care, and the pattern in those timings leaks the key one piece at a time. The cipher stays intact. The clock is the leak. This post shows where the timing comes from, how measurement turns it into key bits, and why blinding and constant time code close it.

What an rsa timing attack actually measures

An rsa timing attack is a side channel attack. A side channel is any way a secret leaks through a physical or observable property of the computation rather than through its output. Time is the easiest one to measure over a network. The RSA private operation is m = c^d mod N, where d is the secret exponent. Raising a number to a large exponent is done by repeated squaring and multiplying, and the exact sequence of operations, plus how long each one runs, is tied to the value of d and to the number being processed. If the code does not actively flatten those differences, the total time carries information about the secret.

Why the time depends on the key

Start with the textbook exponentiation, square and multiply. To compute c^d, the code walks the bits of d from top to bottom. At every bit it squares the running value. When the bit is a one, it also multiplies by c. When the bit is a zero, it does not.

for each bit of d, high to low:
    x = x * x mod N          # always
    if bit == 1:
        x = x * c mod N      # only on a 1 bit

So a one bit costs a square and a multiply, while a zero bit costs only a square. The two take different amounts of time. If you could see the total time of one exponentiation and nothing else, you would already know roughly how many one bits the exponent has. Worse, real implementations let the timing of each step depend on the operands, which ties the timing to where the one bits sit, not just how many there are.

A second source is subtler and is what made remote attacks practical. Fast implementations reduce numbers using Montgomery multiplication, which sometimes performs one extra subtraction at the end, called an extra reduction, to bring the result back into range. Whether that extra step happens depends on the value being multiplied. By choosing ciphertexts that sit just above or just below a multiple of one of the secret prime factors of N, an attacker makes the frequency of extra reductions swing in a way that reveals whether their guess at a key bit was right.

The output of an RSA decryption tells you nothing about the key. The time it took to produce that output tells you a little, and a little, measured a million times, is the whole key.

From a few microseconds to the full key

No single measurement reveals a key bit. Network jitter, scheduling, and cache effects bury the signal in noise. The attack beats the noise with repetition and statistics. The attacker picks ciphertexts designed to make the timing of a correct guess differ from the timing of a wrong guess, sends each one many times, and averages. The true value of a bit shows up as a consistent gap of a few microseconds between the two guesses, visible only once thousands of samples are stacked up.

Researchers demonstrated in 2003 that this works across a local network against a common RSA library, recovering the factorization of the modulus, which is the whole private key, from timing alone. The practical recipe is to recover the secret prime factor one bit at a time: guess the next bit, send ciphertexts near the boundary that bit controls, measure whether decryption sped up or slowed down, keep the guess that matches, and move on. For an invented document service, call it Acme Sign, that signs with RSA and answers each request as fast as it can, an attacker who can time responses precisely can, with enough patience, walk the private key out of the server without a single malformed request. Every query looks like an ordinary client asking for a signature.

The fix: blinding and constant time code

There are two defenses, and strong systems use both.

Blinding breaks the correlation

Blinding makes the timing useless by hiding which number the private key is actually operating on. Before decrypting, the code picks a fresh random value r, multiplies the ciphertext by r^e mod N, runs the private operation on that blinded input, and then divides the result by r to recover the true plaintext:

blinded = c * r^e mod N
result  = blinded^d mod N
m       = result * r^-1 mod N

Because r is random and different every time, the attacker cannot choose the exact value the exponentiation sees, and they cannot align their careful near boundary ciphertexts with anything. The timing still varies, but it no longer correlates with a ciphertext the attacker controls, so the statistics collapse into noise.

Constant time removes the signal at the source

The deeper fix is to make the private operation take the same time no matter what the key or the data is. That means exponentiation routines that perform the same sequence of squares and multiplies regardless of whether a key bit is zero or one, and that do the extra Montgomery reduction every time, or never, rather than conditionally. Constant time code does not branch on secret values and does not index memory at secret dependent addresses. The same discipline protects the small comparison steps around a signature, which is why we wrote a whole post on constant time comparison. Timing leaks are not unique to RSA, and the same measurement mindset underlies the timing variant of a padding oracle attack.

  • Turn on RSA blinding so the attacker cannot aim chosen ciphertexts at the exponentiation.
  • Use a constant time exponentiation that runs the same steps for every key bit.
  • Never branch or index memory on a secret value anywhere in the private path.
  • Keep to well reviewed libraries rather than writing your own modular exponentiation.

For the wider family, see our hub on cryptographic oracle attacks, and for a related break where RSA leaks through its padding rather than its clock, read about rsa signature forgery. A good starting point for the basics is our blog.

The assumption that breaks

One assumption holds this bug up: that a system leaks only through what it says, not through how long it takes to say it. Developers reason about inputs and outputs and rarely about the clock, so a private operation that races to finish quietly publishes the secret it was protecting. You find a flaw like this by asking what an attacker can measure about a response besides its contents, and whether any of it moves with a secret. That is what an autonomous researcher built to test assumptions does: reason about how an app uses a primitive and whether a secret dependent response, including its timing, leaks. Read more on our about page.

Frequently asked questions

What is an RSA timing attack?

It is a side channel attack that recovers an RSA private key by measuring how long the private operation takes instead of breaking the math. The decryption or signing step runs a modular exponentiation with the secret exponent, and the time it takes depends on the key bits and the number being processed. Measured carefully across many requests, those timings leak the key.

Why does RSA decryption time depend on the secret key?

The simple square and multiply method squares at every exponent bit but multiplies only on a one bit, so one bits and zero bits cost different amounts of time. Fast Montgomery reduction adds another signal, because it sometimes performs an extra subtraction whose frequency depends on the operand. An attacker who chooses inputs near the right boundary makes those differences reveal key bits.

Can an RSA timing attack work over a network?

Yes. A single measurement is buried in network jitter and scheduling noise, but sending the same crafted ciphertext many times and averaging exposes a steady gap of a few microseconds between a correct and an incorrect guess. Researchers demonstrated in 2003 that this recovers the factorization of the modulus across a local network, which is the full private key.

How do you prevent an RSA timing attack?

Use both blinding and constant time code. Blinding multiplies the input by a fresh random value before the private operation and divides it out afterward, so the attacker cannot aim chosen ciphertexts at the exponentiation. Constant time code runs the same steps for every key bit and never branches or indexes memory on a secret, which removes the signal at its source. Rely on well reviewed libraries rather than rolling your own.


Put an autonomous researcher on your own systems

UnboundCompute is an autonomous security researcher that reasons about how an application fits together and proves the access control and injection bugs it finds. We are opening a small number of founding design partner seats: private early access pointed at a staging target you choose, and a say in what it looks for. If your team ships software worth pressure testing, apply to the design partner program.