

The most widely used scheme for RSA signing until ~10 years ago (and sadly still prevalent in legacy-ridden protocols like TLS and DNSSEC) is PKCS#1 1.5. Both are short enough to be converted to a number lower than N. So to encrypt arbitrary messages we usually encrypt a symmetric (like, AES) key, and to sign arbitrary messages we sign the hash (like, SHA2) of the message. You might have noticed that m is not a real arbitrary message, but actually a number, that needs to be smaller than N. Only you, having d, can create a signature ( m ^ d mod N) that elevated to e mod N gives exactly m. Signing is the other way around: to sign a message you generate m ^ d mod N, and the recipient uses (N, e) to perform (m ^ d) ^ e = m mod N. To use RSA as a public key encryption primitive, you give out (N, e), Alice sends you m ^ e mod N, and you decrypt performing (m ^ e) ^ d = m mod N. If you keep d secret and publish e and N, it's extremely difficult for an attacker to do d's job (because root and logarithm are hard in modular arithmetics). The cool thing is that if you take a number m and elevate it to both e and d modulus N, you get back m.

When you generate a keypair you get three numbers, N, e and d. If you already know about it or are just interested in the 'sploit, skip the next section. I'm taking the occasion to explain the background and details of the attack, which happens to be one of my favorites because of its simplicity. Update: the issue was assigned CVE-2016-1494. Thankfully keys generated with python-rsa have e=65537 hardcoded, but the library offers a lot of options to import existing keys, which might very well have e=3. The bug allows us to forge signatures for arbitrary messages, as long as the public key has a low exponent ( e), like 3. While looking at the source of python-rsa ( >100K daily downloads) I found it vulnerable to a straightforward variant of the Bleichenbacher'06 attack against RSA signature verification with low public exponent. Bleichenbacher'06 signature forgery in python-rsa
