RustCrypto / RSA

RSA implementation in pure Rust
Apache License 2.0
536 stars 148 forks source link

RSA key generation comparatively slow #144

Open beamer159 opened 2 years ago

beamer159 commented 2 years ago

I need to frequently generate RSA keys in bulk. I am using the following Rust code to generate a key:

let rsa_key = rsa::RsaPrivateKey::new(&mut rand::thread_rng(), 2048).unwrap();

Running this code in release mode to generate 100 RSA keys takes about 18 seconds on my machine. In comparison, I used the following code in C (OpenSSL) and C# (CNG) to generate the same-size RSA key.

C - OpenSSL

RSA *rsa_key = RSA_new();
BIGNUM *e = BN_new();
BN_set_word(e, RSA_F4);
RSA_generate_key_ex(rsa_key, 2048, e, NULL);

C# - CNG

var rsaKey = new RSACng(2048).Key;

To generate 100 keys, the C code takes about 6.7 seconds and the C# code takes about 5.5 seconds. I was surprised that the Rust key generation took about 3x more time than both C and C#.

aloucks commented 2 years ago

~I ran into this a while back as well. The bottleneck appears to be in the prime number generation~:

https://github.com/RustCrypto/RSA/blob/7395997c40b0f2c0bdb362b2998cbf9250408276/src/algorithms.rs#L99

EDIT: After benchmarking this some more, it actually looks like the number of primes used to generate the key is the influencing factor. I increased the number of primes from 2 to 3 (based on the table 1 in the PDF linked below) and saw the time it took to generate 100 keys dropped from about 16 seconds to 7 seconds.

https://github.com/RustCrypto/RSA/blob/7395997c40b0f2c0bdb362b2998cbf9250408276/src/key.rs#L279

https://cacr.uwaterloo.ca/techreports/2006/cacr2006-16.pdf

dignifiedquire commented 1 year ago

The main reason asfaik is that the underlying operations are nowhere nearly as optimized as the code in OpenSSL and whatever library C# is calling into.

@aloucks that will generate a different RSA key setup though, and most applications today assume using 2 primes and not more asfaik.

jellevos commented 1 year ago

In https://github.com/jellevos/scicrypt/blob/master/scicrypt-numbertheory/src/lib.rs I have implemented an algorithm that is almost exactly the same as OpenSSL's. Depending on the machine and parameters it is slightly faster or slightly slower than OpenSSL. I am happy to give it a try to reimplement it in this crate (the algorithm is not complicated). Of course, if the bottleneck is the underlying arithmetic, then it might not make a large difference.

tarcieri commented 1 year ago

@jellevos would definitely be curious what the performance is if you did port it over

r10s commented 1 year ago

ftr: older issue with similar topic: https://github.com/RustCrypto/RSA/issues/29

darconeous commented 1 year ago

Once https://github.com/dignifiedquire/num-bigint/pull/48 lands, prime generation should be a little faster.

dignifiedquire commented 1 year ago

@darconeous next_prime is not actually used for prime generation in this crate, so that won't help unfortunately.

darconeous commented 1 year ago

do'h!