You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The author of this Stack Overflow question tried to experiment with weak private keys by using a very, very small value for one of the primes in the key. In the following private key, q has been set to 5:
While this is otherwise a terrible idea, this key triggers a catastrophically slow while loop in the PyCryptodome implementation of step 3 of the RSA decryption algorithm:
# Step 3: Compute m' = c'**d mod n (ordinary RSA decryption)
m1=pow(cp, self._d% (self._p-1), self._p)
m2=pow(cp, self._d% (self._q-1), self._q)
h=m2-m1
whileh<0:
h+=self._q
h= (h*self._u) %self._q
mp=h*self._p+m1
Because q is so small but p is a 617-digit prime number, m1 is a 616-digit integer, and m2 is 3, and so h is a negative 616-digit integer. The while h < 0: h += self._q loop is going to take a very, very, very long time (abs(h // self._q) is itself a 615 digit number). This is going to very long time. Adding a small IntegerGMP(5) value to a 616-digit IntegerGMP() value 1 million times already takes nearly 6 seconds on my aging MacBook Pro:
timeit("a + b", "from Crypto.Math._IntegerGMP import IntegerGMP as H; a = H(-529888206800322351142280698970509553244088870105926093960960600839997948364537263924658051221855219286822834908160253952313431263065035892252247530580840707934254014192645042780064071400938165792458671917549294961637063901428635522475550885330295366860440266592481901428697979715456902249133738633092402578072834537512045684962133176512203248846326955899359525113708331947304401283815041620003402445741404924361709787545141518988924507726836779489762118740731196007268258996956015186886831392340919980371282865371496239488099989353283964607756716132847721450221986689589881754517900556993453537792486255692015472770); b = H(5)")
5.970772444999966
10 ^ 609 times that time results in a runtime that takes 607 digits just to express the number of centuries we'd have to wait.
The while h < 0: h += h loop could trivially be replaced with a modulus operation, however; Python's % operator produces the remainder with the same sign as the divisor. So when I replace the while h < 0: loop with a modulus operation the result is almost instantaneous:
ifh<0:
h=h%self._q# or h %= self._q
The cost of a single % operation is about the same as addition (timeit takes 6.428032868000173 seconds for a million repeats on the same aging laptop), but it only has to be executed once. The time taken when q is a large prime with comparable magnitude barely increases.
The text was updated successfully, but these errors were encountered:
And to note the security implications: in a scenario where code using PyCryptodome accepts arbitrary private keys, this could be used to DOS that system.
The author of this Stack Overflow question tried to experiment with weak private keys by using a very, very small value for one of the primes in the key. In the following private key, q has been set to 5:
The first prime (p) is a 617-digit value:
While this is otherwise a terrible idea, this key triggers a catastrophically slow
while
loop in the PyCryptodome implementation of step 3 of the RSA decryption algorithm:pycryptodome/lib/Crypto/PublicKey/RSA.py
Lines 158 to 165 in efdb406
Because
q
is so small butp
is a 617-digit prime number,m1
is a 616-digit integer, andm2
is 3, and soh
is a negative 616-digit integer. Thewhile h < 0: h += self._q
loop is going to take a very, very, very long time (abs(h // self._q)
is itself a 615 digit number). This is going to very long time. Adding a smallIntegerGMP(5)
value to a 616-digitIntegerGMP()
value 1 million times already takes nearly 6 seconds on my aging MacBook Pro:10 ^ 609 times that time results in a runtime that takes 607 digits just to express the number of centuries we'd have to wait.
The
while h < 0: h += h
loop could trivially be replaced with a modulus operation, however; Python's%
operator produces the remainder with the same sign as the divisor. So when I replace thewhile h < 0:
loop with a modulus operation the result is almost instantaneous:The cost of a single
%
operation is about the same as addition (timeit takes 6.428032868000173 seconds for a million repeats on the same aging laptop), but it only has to be executed once. The time taken when q is a large prime with comparable magnitude barely increases.The text was updated successfully, but these errors were encountered: