I need to use basic RSA cryptography in my program so I use the RSACryptoServiceProvider class to do so.
I noticed it generates keys much faster than PyCrypto (Python) for example.
Here are some benchmarks I made:
Execution times (.NET with RSACryptoServiceProvider)
Average generation time for 1024-bit key pair: 111,2 ms
Average generation time for 2048-bit key pair: 394,8 ms
Average generation time for 3072-bit key pair: 594 ms
Average generation time for 4096-bit key pair: 872,4 ms
Average generation time for 5120-bit key pair: 3351,4 ms
Average generation time for 6144-bit key pair: 4644,2 ms
Average generation time for 7168-bit key pair: 10052,8 ms
Average generation time for 8192-bit key pair: 16105,8 ms
Execution times (Python with PyCrypto)
Average generation time for 1024-bit key pair: 1.19569948638 s
Average generation time for 2048-bit key pair: 2.43145552844 s
Average generation time for 3072-bit key pair: 12.8203488201 s
Average generation time for 4096-bit key pair: 16.4437521276 s
Average generation time for 5120-bit key pair: 58.6469382781 s
Average generation time for 6144-bit key pair: 166.814121751 s
Average generation time for 7168-bit key pair: 132.13567301 s
Average generation time for 8192-bit key pair: 218.305013463 s
Ratio (Python/.NET) :
1024-bit key pair: 10,75
2048-bit key pair: 6,16
3072-bit key pair: 21,58
4096-bit key pair: 18,85
5120-bit key pair: 17,50
6144-bit key pair: 35,92
7168-bit key pair: 13,14
8192-bit key pair: 13,55
As you can see, Python is about 17 times slower than .NET. Is Python really slow or does .NET use some kind of optimization to generate keys?
Tests were run on Windows 7 Ultimate 64-bit with an Intel Core i7 2600.
I used the following code to get these results:
C#
List<List<long>> executionTimes = new List<List<long>>();
int step = 1024;
for (int bits = 1024; bits <= 8192; bits += step) // 1024-bit to 8192-bit key pair
{
executionTimes.Add(new List<long>());
for (int i = 0; i < 5; ++i) // Run the test 10 times to compute an average
{
Console.WriteLine("Generating " + bits + "-bit key pair...");
Stopwatch s = Stopwatch.StartNew();
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(bits); // Doesn't actually generate the key pair
rsa.ExportParameters(true); // Force generation of the key pair
s.Stop();
executionTimes[executionTimes.Count - 1].Add(s.ElapsedMilliseconds);
Console.WriteLine("Key pair generated. Time: " + s.ElapsedMilliseconds.ToString() + " ms\r\n");
}
}
for (int i = 1; i <= executionTimes.Count; ++i)
Console.WriteLine("Average generation time for " + (i * step).ToString() + "-bit key pair: " + executionTimes[i - 1].Average().ToString() + " ms");
Console.ReadLine();
Python
import time
from Crypto.PublicKey import RSA
execution_times = list()
step = 1024
for bits in range(1024, 8192 + 1, step): # 1024-bit to 8192-bit key pair
execution_times.append(list())
for i in range(5):
print("Generating " + str(bits) + "-bit key pair...")
t = time.clock()
RSA.generate(bits) # Generate key pair
t = time.clock() - t
execution_times[len(execution_times) - 1].append(t)
print("Key pair generated. Time: " + str(t) + " s\r\n");
for i in range(1, len(execution_times) + 1, 1):
print("Average generation time for " + str(i * step) + "-bit key pair: " + str(sum(execution_times[i - 1]) / len(execution_times[i - 1])) + " s")
Why is C# so much faster at generating keys than Python?