pyca / cryptography

cryptography is a package designed to expose cryptographic primitives and recipes to Python developers.
https://cryptography.io
Other
6.42k stars 1.47k forks source link

Add rsa_recover_private_exponent function #11193

Closed dlenskiSB closed 4 days ago

dlenskiSB commented 6 days ago

Given the RSA public exponent (e), and the RSA primes (p, q), it is possible to calculate the corresponding private exponent d = e⁻¹ mod λ(n) where λ(n) = lcm(p-1, q-1).

With this function added, it becomes possible to use the library to reconstruct an RSA private key given only p, q, and e:

from cryptography.hazmat.primitives.asymmetric import rsa

n = p * q
d = rsa.rsa_recover_private_exponent(e, p, q)  # newly-added piece
iqmp = rsa.rsa_crt_iqmp(p, q)                  # preexisting
dmp1 = rsa.rsa_crt_dmp1(d, p)                  # preexisting
dmq1 = rsa.rsa_crt_dmq1(d, q)                  # preexisting

assert rsa.rsa_recover_prime_factors(n, e, d) in ((p, q), (q, p))  # verify consistency

privk = rsa.RSAPrivateNumbers(p, q, d, dmp1, dmq1, iqmp, rsa.RSAPublicNumbers(e, n)).private_key()

Older RSA implementations, including the original RSA paper, often used the Euler totient function ɸ(n) = (p-1) * (q-1) instead of λ(n). The private exponents generated by that method work equally well, but may be larger than strictly necessary (λ(n) always divides ɸ(n)). This commit additionally implements _rsa_recover_euler_private_exponent, so that tests of the internal structure of RSA private keys can allow for either the Euler or the Carmichael versions of the private exponents.

It makes sense to expose only the more modern version (using the Carmichael totient function) for public usage, given that it is slightly more computationally efficient to use the keys in this form, and that some standards like FIPS 186-4 require this form. (See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf#page=63)

reaperhulk commented 4 days ago

Looks like you'll need to add totient to docs/spelling_wordlist.txt

dlenskiSB commented 4 days ago

Looks like you'll need to add totient to docs/spelling_wordlist.txt

@reaperhulk Yep, just fixed that. (And added Euler and Carmichael while we're at it.)