I think in general your questions on performance are answered here. wikipedia : modular exponentiation
The article describes
- Direct exponentiation
- Memory efficient exponentiation
- Binary exponentiation
Direct Exponentiation
raise to the power e and take the modulo. This is straight forward, but the size of the number pre modulo is extermely large.
Memory efficient exponentiation
Replacing the power operation with a multiply e times, allows the accumulated result to always be within the modulo range. This limits the size of the bignum and speeds up the operation.
Binary exponentiation
If you convert the power to a binary number
if e = 13 => 1101 pow(n, 13) = pow( n, 8) * pow(n,4) * pow(n, 1) So for an m bit exponent, then only about m operations need to be done.
Combining the memory efficient and binary exponentiation solves most of the performance.
Python offers an implementation of these improvements using the 3 argument power function e.g.
>>> import timeit >>> t = timeit.Timer( 'print(pow( 10,14918179, 15372757))' ) >>> t.timeit(1) 10140931 0.06365180000000237 >>> u = timeit.Timer( 'print(pow( 10,14918179) % 15372757)' ) >>> u.timeit(1) 10140931 15.021656000000007
The 3 parameter of pow takes .06s whilst the 2 parameter version of pow takes 15 seconds.
pow()? If not, you should be. Also note that a simple Python script using Python's generic integer math will never be as fast as a C library specifically optimized for RSA. But with that change (and reasonable algorithms) it should at least get close to the same ballpark.