2011-03-14 24 views
2

VerifyData的性能如此糟糕以至於該函數幾乎無用,或者我在下面的代碼中做了非常錯誤的操作?RSACryptoServiceProvider.VerifyData的爛性能?

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) 

在2.1 GHz雙核32位XP上,100次調用VerifyData需要3秒。

我也嘗試用重用的SHA1CryptoServiceProvider對象替換「SHA1」字符串(在循環中沒有新的實例化),但這沒有什麼區別。

對於單個VerifyData調用需要0.03秒 - 這裏發生了什麼?

編輯/更新:剛剛嘗試編寫F#函數,使用BigInteger.ModPow,我自己的填充函數和SHA1CryptoServiceProvider.ComputeHash。 100次迭代在0.07秒內完成,比RSACryptoServiceProvider快40倍。 (這些結果一定是錯誤的,稍後會修改)

+0

在這一天結束時,性能下降不是一個錯誤,它的一個特點。 http://codahale.com/how-to-safely-store-a-password/ – Juliet 2011-03-14 21:23:06

+3

@Juliet:這隻適用於你想減慢暴力強度的情況,而且不應該通過慢速實現來完成,但設計相當緩慢。 – 2011-03-14 21:28:40

+0

@Juliet:我所做的不好的表現是檢查簽名,然後你通常只能訪問公鑰。 – 2011-03-14 23:46:05

回答

0

不僅發生了SHA1散列,而且還發生了非對稱RSA操作,而且這種操作相對較慢(但是,30毫秒仍然有點慢一個單一的1024位操作)。

您是否試過使用自己的加密基元的替代加密實現,如BouncyCastle或我們的SecureBlackbox?嘗試執行此操作來檢查它們在系統上顯示的性能。

同時,我們也注意到,一些基本的加密操作花費更多的時間在某些非常強大的處理器(四核)比舊的雙核(比如AES的速度是雙核筆記本6 MB/s的四核打擊30 MB /秒)。即系統架構以某種方式影響託管代碼的速度。

+0

我還沒有試過Bouncycastle,但我剛剛使用bigint(System.Numerics.BigInteger來自非F#langs)完成了我自己的函數。它在同一臺計算機上以0.07秒完成100次迭代。我會用結果更新我的OP。 – 2011-03-14 20:32:05

0

我切換時間使用System.Diagnostics.Stopwatch,以確保您沒有受到不良分辨率的影響。在我的雙核筆記本電腦上運行2年的代碼,平均需要270毫秒100次迭代。

我對循環部分進行計時,耗時大約70毫秒,因此大部分工作都是在循環之前完成的。進一步分解它,實際上SignData就是這裏的豬,即使它在基準測試中只被調用一次,也需要大約210毫秒。

當然,我們使用的是不同的機器,但70毫秒是您從自己的驗證代碼中獲得的?

更改計時器:

let timer f = 
    let sw = System.Diagnostics.Stopwatch() 
    sw.Start() 
    f() |> ignore 
    sw.Stop() 
    sw.ElapsedMilliseconds 

樣本崩潰:

Construct cryptoprovider took 0 
Create test array took 0 
rnd.NextBytes took 0 
rsaSP.SignData took 211 
VerifyData took 75 
100 iterations took 287L 
+0

我的時間與Eugene所說的不同架構相吻合。我很想知道您使用的是哪種架構,以及結果有何不同。 – 2011-03-26 22:26:52

+0

Ooops,我在定時部分包含了簽名和密鑰生成,這是一個令人尷尬的巨大錯誤。我明天將重新運行測試並在此發佈我的新結果。 – 2011-03-27 00:56:07

+0

我剛剛用您的秒錶代碼再次嘗試此測試,並將簽名/ keygen移出循環。在英特爾雙核T3400 @ 2.16 GHz運行32位XP上,100次迭代耗時2325毫秒。在運行Vista x64的Q9550 @ 2.8 GHz上,耗時770毫秒。我用F#bigint得到的70ms結果肯定是一個拙劣的替補。現在我正在做一個更徹底的測試,與F#bigint和MPIR(= Windows的GMPLib)進行比較。結果將被張貼! – 2011-03-27 11:55:42