Known Flaws in RSA, and How to Fix Them

CS 463 Lecture, Dr. Lawlor

Flaw: Prime Generation

The prime numbers p and q need to be truly unpredictable, not just random looking.  This means calling a deterministic random number generator like "rand" is completely insufficient--consider there are only 4 billion possible values that can be passed to srand(). 

Back in 1996, this was a known flaw in the then wildly popular web browser Netscape.

The fix: make sure your implementation is using a good random number source like /dev/random or CryptGenRandom (but don't use Dual_EC_DRBG).

Flaw: Side Channel (Timing, Heat, etc) Attacks

Each operation used in RSA encryption is a slow multi-precision operation, so it's easier to measure the time taken to do each sub-multiplication in an exponentiation (compared to, for example, the sub-clockcycle time to do the carry bits in a normal addition).  This is bad, because tons of operations have data-dependent timing--for example, decrypting data (m=cd mod n) means looking at each bit of your private key, and choosing to include a multiple of c.  This sort of attack can be extremely high precision when coming from a different VM on the same cloud server.

Possible fixes:

Flaw: Message Enumeration

Recall that:
To encrypt a message m into ciphertext c, use the public key e: c = me mod n
To decrypt ciphertext c back into the message m, use your private key d: m=cd mod n

Theoretically, you need the private key to decrypt the message.  However, anybody can check if a possible message m encrypts to the intercepted ciphertext c, because anybody can encrypt a message for you.  In other words, public key "encryption" works more like a hash function, where anybody can check if the hashes match.

Secret key ciphers don't have this flaw, because you need the key to encrypt.

The fix is to pad each message with random data--the exact analog of using a salted hash for passwords.  256 bits is enough to make an attacker's search space entirely infeasible.  Some follow this with a weak encryption scheme, like the hash-based one round Feistel used in OAEP, to ensure that a partial break won't reveal anything valuable (it also messes up multiplicative structure, below).

Flaw: Multiplicative Structure

Since RSA is based on simple exponentiation, encrypting (or decrypting) the product of two messages gives the product of the two ciphertexts:
c = me mod n
c' = m'e mod n
c * c' = me * m'e = (m * m')e mod n

There are enough ways to exploit this that you should never encrypt or sign a raw message, only a carefully packaged message. 

For encryption, see the previous fix OAEP.

For signing, several options exist, but the most popular signing scheme is the hash based RSASSA-PKCS1-v1.5.  This boils down to signing a binary value consisting of: