Is the performance of VerifyData so bad that the function is practically useless, or am I doing something very wrong in the code below?
open System
open System.Security.Cryptography
let keySize = 1024 // bits
let testDataLen = 1000
let iterations = 100
let hashAlg = "SHA1"
let timer f =
let start = DateTime.Now
f() |> ignore
let finish = DateTime.Now
finish - start
let bench () =
use rsaSP = new RSACryptoServiceProvider(keySize)
let rnd = Random()
let data = Array.create testDataLen 0uy
rnd.NextBytes data
let signature = rsaSP.SignData(data, hashAlg)
let isValid = [for i in 1..iterations -> rsaSP.VerifyData(data, hashAlg, signature)]
|> List.forall id
if not isValid then failwith "Bad signature."
printfn "%d iterations took %A" iterations (timer bench)
100 calls to VerifyData takes a full 3 seconds on a 2.1 GHz Dual-Core on 32 bit XP.
I've also tried replacing the "SHA1" string with a SHA1CryptoServiceProvider object that is reused (no new instantiations in the loop), but that makes no difference.
0.03 seconds for a single VerifyData call - what's going on here?
Edit/Update: Just tried writing F# functions, using BigInteger.ModPow, my own padding function and SHA1CryptoServiceProvider.ComputeHash. The 100 iterations finish in 0.07 seconds, which is 40 times faster than RSACryptoServiceProvider. (Those results must have been wrong. Will revise later.)
Delay while calling RSACryptoServiceProvider SignData or VerifyData methods
There's not just SHA1 hashing taking place, but also an asymmetric RSA operation, and this one is relatively slow (however, 30 msec is still a bit slow for a single 1024-bit operation).
Did you try alternative crypto implementations that use their own cryptographic primitives, such as BouncyCastle or our SecureBlackbox? Try doing this to check what performance they show on your system.
Also we noticed that some basic crypto operations take much more time on certain quite powerful processors (QuadCore) than on older DualCore (say speed of AES is 6 Mb/s on QuadCore against 30 Mb/s on DualCore notebook). I.e. system architecture affects speed of managed code somehow.
I switched timing to use System.Diagnostics.Stopwatch, to make sure you weren't suffering from bad resolution. Running your code on my dual-core laptop of 2 years it takes on average 270 milliseconds with 100 iterations.
I timed just the looping part, that takes around 70 milliseconds, so the bulk of the work is done prior to looping. Breaking it down further, it is actually SignData that is the hog here, it takes around 210 milliseconds even though it is called only once in the benchmark.
Of course, we are using different machines, but 70 milliseconds is what you got out of your own verifying code?
Changes to timer:
let timer f =
let sw = System.Diagnostics.Stopwatch()
sw.Start()
f() |> ignore
sw.Stop()
sw.ElapsedMilliseconds
Sample breakdown:
Construct cryptoprovider took 0
Create test array took 0
rnd.NextBytes took 0
rsaSP.SignData took 211
VerifyData took 75
100 iterations took 287L