Factoring RSA Keys With TLS Perfect Forward Secrecy


Florian Weimer from the Red Hat Product Security team has just released a technical report entitled: "Factoring RSA Keys With TLS Perfect Forward Secrecy"

Wait what happened?

A team of researchers ran an attack for nine months, and from 4.8 billion of ephemeral handshakes with different TLS servers they recovered hundreds of private keys.

The theory of the attack is actually pretty old, Lenstra's famous memo on the CRT (short for Chinese Remainder Theorem) optimization was written in 1996. Basically, when using the CRT optimization to compute a RSA signature, if a fault happens, a simple computation will allow the private key to be recovered. This kind of attacks are usually thought and fought in the realm of smartcards and other embedded devices, where faults can be induced with lasers and other magical weapons.

The research is novel in a way because they made use of Accidental Faults Attack, which is one of the rare kind of remote side-channel attacks. This is interesting. The oldest passive form of Accidental Fault Attack I can think of is Bit Squatting that might go back to 2011 at that defcon talk.

But first, what is vulnerable?

Any library that uses the CRT optimization for RSA might be vulnerable. A cheap countermeasure would be to verify the signature after computing it, which is what most libraries do. The paper has a nice list of who is doing that.

Implementation Verification
cryptlib 3.4.2 disabled by default
GnuPG yes
GNUTLS see libgcrypt and Nettle
Go 1.4.1 no
libgcrypt 1.6.2 no
Nettle 3.0.0 no
NSS yes
ocaml-nocrypto 0.5.1 no
OpenJDK 8 yes
OpenSSL 1.0.1l yes
OpenSwan 2.6.44 no
PolarSSL 1.3.9 no


But it is not just about the library you're using. Your server still has to be defective to produce a fault. The paper also has a nice table displaying what vendors, in their experiments, were most prone to have this vulnerability.

Vendor Keys PKI Rate
Citrix 2 yes medium
Hillstone Networks 237 no low
Alteon/Nortel 2 no high
Viprinet 1 no always
QNO 3 no medium
ZyXEL 26 no low
BEJY 1 yes low
Fortinet 2 no very low


If you're using one of these, you might want to check with your vendor if a firmware update or other solutions is available after the discovery of this attack. You might also want to revoke your keys.

Since the tests were done on a broad scale and not on particular machines, it is obvious that more are vulnerable to this attack. Also, only instances connected to internet that offered TLS on port 443 were tested. The vulnerability could potentially exist in any stack using this CRT optimization with RSA.

The first thing you should do is asses where in your stack the RSA algorithm is used to sign. Does it use CRT? If so, does it verify the signature? Note that the blinding techniques we talked about in one of our cryptography bulletin (May first of this year) will not help.

What can cause your server to produce such erroneous signatures?

They list five reasons in the paper:

  • Old or vulnerable libraries that have broken operations on integer. For example CVE-2014-3570 the square operations of OpenSSL was not working properly for some inputs.
  • Race conditions, when applications are multithreaded.
  • Arithmetic unit of the CPU is broken by design or by fatigue.
  • Corruption of the private key.
  • Errors in the CPU cache, other caches or the main memory.

Note that at the end of the paper, they investigate if special hardware might be the cause and end up with the conclusion that several devices leaking the private keys were using Cavium hardware, and in some cases their "custom" version of OpenSSL.

I'm curious. How does that work?


Remember, RSA signature is basically y = x^d modulo n with x the message, d the private key and n the public modulus. Also, you might want to use a padding system but we won't cover that here. You can verify a signature by doing y^e modulo n and verify if it is equal to x (with e the public exponent).

CRT is an optimization that allows one to compute the signatures in Z_p and Z_q and then combine it into Z_n (remember n = pq). It's way faster like that.

So basically what you do is:

  • y_p = x^d modulo p
  • y_q = x^d modulo q

and then combine these two values to get the signature:

y = y_p q (q^{-1} modulo p) + y_q p (p^{-1} modulo q) modulo n

And you can verify yourself, this value will be equals to y_p modulo p and y_q modulo q.

The vulnerability

Let's say that an error occurs in only one of these two elements. For example, y_p is not correctly computed. We'll call it Y_p instead. It is then is combined with a correct y_q to produce a wrong signature that we'll call Y .

So you should have:

  • Y = Y_p modulo p
  • Y = y_q modulo q

Let's notice that if we raise that to the power e and remove x from it we get:

  • Y^e - x = Y_p^e - x = a modulo p
  • Y^e - x = y_q^e - x = 0 modulo q

This is it. We now know that q divides Y^e - x while it also divides n. Whereas p doesn't divide Y^e - x anymore. We just have to compute the Greatest Common Divisor of n and Y^e - x to recover q.

The attack

The attack could potentially work on anything that displays a RSA signature. But the paper focuses itself on TLS.

A normal TLS handshake is a two round trip protocol that looks like this:



The client (the first person who speaks) first sends a ClientHello packet, which is filled with bytes saying things like "this is a handshake", "this is TLS version 1.0", "I can use this algorithm for the handshake", "I can use this algorithm for encrypting our communications", etc...

Here's what it looks like in Wireshark:


client hello

The server (the second person who speaks) replies with 3 messages: a similar ServerHello, a message with his certificate (and that's how we authenticate the server) and a ServerHelloDone message only consisting of a few bytes saying "I'm done here!".

A second round trip is then done where the client encrypts a key with the server's public key and they later use it to compute the TLS shared key. We won't cover these messages.

Another kind of handshake can be performed if both the client and the server accepts ephemeral key exchange algorithms (Diffie-Hellman or Elliptic Curve Diffie-Hellman). This is to provide Perfect Forward Secrecy: if the conversations are recorded by a third party, and the private key of the server is later recovered, nothing will be compromised. Instead of using the server's public key to compute the shared key, the server will generate a ephemeral public key and use it to perform an ephemeral handshake. It usually just uses this key for this session or for a limited number of sessions.



An extra packet called ServerKeyExchange is sent. It contains the server's ephemeral public key.

Interestingly the signature is not computed over the algorithm used for the ephemeral key exchange, that led to a long series of attack which recently ended with FREAK and Logjam.

By checking if the signature is correctly performed, this is how Florian Weimer checked for the potential vulnerability.

I'm a researcher, what's in it for me?

Well what are you waiting for? Go read the paper!

But here is a list of what I found interesting:

  • instead of DDoSing one target, they broadcasted their attack:
  • "We implemented a crawler which performs TLS handshakes and looks for miscomputed RSA signatures. We ran this crawler for several months. The intention behind this configuration is to spread the load as widely as possible. We did not want to target particular servers because that might have been viewed as a denial-of-service attack by individual server operators. We assumed that if a vulnerable implementation is out in the wild and it is somewhat widespread, this experimental setup still ensures the collection of a fair number of handshake samples to show its existence. We believe this approach — probing many installations across the Internet, as opposed to stressing a few in a lab — is a novel way to discover side-channel vulnerabilities which has not been attempted before."
  • They used public information to choose what to target, like scans.io, tlslandscape and certificate-transparency.
  • Some TLS servers need a valid Server Name Indication to complete a handshake, so connecting on port 443 of random IPs should not be very efficient. But they found that it was actually not a problem and most key found like that were from weird certificates that wouldn't even be trusted by your browser.
  • To avoid too many DNS resolutions they bypassed the TTL values and cached everything (they used PowerDNS for that)
  • They guess what devices were used to perform the TLS handshakes from what was written in the x509 certificates in the subject distinguished name field or Common Name field
  • They used SSL_set_msg_callback() to avoid modifying OpenSSL.

Published date:  04 September 2015

Written by:  David Wong

comments powered by Disqus

Filter By Service

Filter By Date