-
Notifications
You must be signed in to change notification settings - Fork 114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Private key operations don't use CRT #163
Comments
This is despite the code actually calculating the values necessary for CRT: Lines 370 to 379 in 4beb68d
|
I think I initially just added the code for computing those values for exporting to some PKCS standard file. Good catch, thanks. |
I wrote this little benchmark, just to see the effect: import timeit
import rsa
from rsa import common, transform, core, pkcs1
with open("privatekey.pem", "rb") as infile:
priv_key: rsa.PrivateKey = rsa.PrivateKey.load_pkcs1(infile.read())
with open(__file__, "rb") as infile:
message = infile.read(500)
keylength = common.byte_size(priv_key.n)
padded = pkcs1._pad_for_encryption(message, keylength)
payload = transform.bytes2int(padded)
def decrypt_standard():
return core.decrypt_int(payload, priv_key.d, priv_key.n)
def decrypt_crt():
s1 = pow(payload, priv_key.exp1, priv_key.p)
s2 = pow(payload, priv_key.exp2, priv_key.q)
h = ((s1 - s2) * priv_key.coef) % priv_key.p
c = s2 + priv_key.q * h
return c
crypto_standard = decrypt_standard()
crypto_crt = decrypt_crt()
assert crypto_standard == crypto_crt, f"Expected {crypto_standard} == {crypto_crt}"
number = 10
time = timeit.timeit(decrypt_standard, globals=locals(), number=number) / number
print(f"decrypt_standard: {time:.4f} sec average")
time = timeit.timeit(decrypt_crt, globals=locals(), number=number) / number
print(f"decrypt_crt : {time:.4f} sec average") The result:
So yes, CRT is 3x faster in this case. Update: this is for decryption, not encryption. |
the same change can be applied to creation of signatures |
- Update from 4.0 to 4.8 - Update of rootfile - Changelog - Switch to [Poetry](https://python-poetry.org/) for dependency and release management. - Compatibility with Python 3.10. - Chain exceptions using `raise new_exception from old_exception` ([#157](sybrenstuvel/python-rsa#157)) - Added marker file for PEP 561. This will allow type checking tools in dependent projects to use type annotations from Python-RSA ([#136](sybrenstuvel/python-rsa#136)). - Use the Chinese Remainder Theorem when decrypting with a private key. This makes decryption 2-4x faster ([#163](sybrenstuvel/python-rsa#163)). - Fix picking/unpickling issue introduced in 4.7 ([#173](sybrenstuvel/python-rsa#173)) - Fix threading issue introduced in 4.7 ([#173](sybrenstuvel/python-rsa#173)) - Fix [#165](sybrenstuvel/python-rsa#165): CVE-2020-25658 - Bleichenbacher-style timing oracle in PKCS#1 v1.5 decryption code - Add padding length check as described by PKCS#1 v1.5 (Fixes [#164](sybrenstuvel/python-rsa#164)) - Reuse of blinding factors to speed up blinding operations. Fixes [#162](sybrenstuvel/python-rsa#162). - Declare & test support for Python 3.9 Version 4.4 and 4.6 are almost a re-tagged release of version 4.2. It requires Python 3.5+. To avoid older Python installations from trying to upgrade to RSA 4.4, this is now made explicit in the `python_requires` argument in `setup.py`. There was a mistake releasing 4.4 as "3.5+ only", which made it necessary to retag 4.4 as 4.6 as well. No functional changes compared to version 4.2. Version 4.3 and 4.5 are almost a re-tagged release of version 4.0. It is the last to support Python 2.7. This is now made explicit in the `python_requires` argument in `setup.py`. Python 3.4 is not supported by this release. There was a mistake releasing 4.4 as "3.5+ only", which made it necessary to retag 4.3 as 4.5 as well. Two security fixes have also been backported, so 4.3 = 4.0 + these two fixes. - Choose blinding factor relatively prime to N. Thanks Christian Heimes for pointing this out. - Reject cyphertexts (when decrypting) and signatures (when verifying) that have been modified by prepending zero bytes. This resolves CVE-2020-13757. Thanks Carnil for pointing this out. - Rolled back the switch to Poetry, and reverted back to using Pipenv + setup.py for dependency management. There apparently is an issue no-binary installs of packages build with Poetry. This fixes [#148](sybrenstuvel/python-rsa#148) - Limited SHA3 support to those Python versions (3.6+) that support it natively. The third-party library that adds support for this to Python 3.5 is a binary package, and thus breaks the pure-Python nature of Python-RSA. This should fix [#147](sybrenstuvel/python-rsa#147). - Added support for Python 3.8. - Dropped support for Python 2 and 3.4. - Added type annotations to the source code. This will make Python-RSA easier to use in your IDE, and allows better type checking. - Added static type checking via [MyPy](http://mypy-lang.org/). - Fix [#129](sybrenstuvel/python-rsa#129) Installing from source gives UnicodeDecodeError. - Switched to using [Poetry](https://poetry.eustace.io/) for package management. - Added support for SHA3 hashing: SHA3-256, SHA3-384, SHA3-512. This is natively supported by Python 3.6+ and supported via a third-party library on Python 3.5. - Choose blinding factor relatively prime to N. Thanks Christian Heimes for pointing this out. - Reject cyphertexts (when decrypting) and signatures (when verifying) that have been modified by prepending zero bytes. This resolves CVE-2020-13757. Thanks Adelapie for pointing this out. Signed-off-by: Adolf Belka <[email protected]> Reviewed-by: Peter Müller <[email protected]>
The private key operations:
python-rsa/rsa/pkcs1.py
Lines 270 to 300 in 4beb68d
python-rsa/rsa/key.py
Lines 440 to 453 in 4beb68d
python-rsa/rsa/core.py
Lines 29 to 53 in 4beb68d
Use simple
pow(x, d, n)
operation to calculate the signature or decrypt a message. Becausen
is composite, it's possible to use Chinese remainder theorem. This will speed up the private key operations by a factor of 2 up to 4.I.e. Instead of doing:
the code should precompute values for the CRT (with
d
used instead ofekey
as the private exponent):and then it can compute the power modulo like so:
(or course, as the CRT parameters are closely related to p and q, they should be considered part of the private key and treated accordingly)
The text was updated successfully, but these errors were encountered: