1{-# LANGUAGE OverloadedStrings #-} 2{-# LANGUAGE ExistentialQuantification #-} 3{-# LANGUAGE FlexibleContexts #-} 4{-# LANGUAGE TypeFamilies #-} 5module Main where 6 7import Gauge.Main 8 9import Crypto.Cipher.AES 10import qualified Crypto.Cipher.AESGCMSIV as AESGCMSIV 11import Crypto.Cipher.Blowfish 12import Crypto.Cipher.CAST5 13import qualified Crypto.Cipher.ChaChaPoly1305 as CP 14import Crypto.Cipher.DES 15import Crypto.Cipher.Twofish 16import Crypto.Cipher.Types 17import Crypto.ECC 18import Crypto.Error 19import Crypto.Hash 20import qualified Crypto.KDF.BCrypt as BCrypt 21import qualified Crypto.KDF.PBKDF2 as PBKDF2 22import Crypto.Number.Basic (numBits) 23import Crypto.Number.Generate 24import qualified Crypto.PubKey.DH as DH 25import qualified Crypto.PubKey.ECC.Types as ECC 26import qualified Crypto.PubKey.ECC.Prim as ECC 27import qualified Crypto.PubKey.ECDSA as ECDSA 28import qualified Crypto.PubKey.Ed25519 as Ed25519 29import qualified Crypto.PubKey.EdDSA as EdDSA 30import Crypto.Random 31 32import Control.DeepSeq (NFData) 33import Data.ByteArray (ByteArray, Bytes) 34import qualified Data.ByteString as B 35 36import qualified Crypto.PubKey.ECC.P256 as P256 37 38import Number.F2m 39 40data HashAlg = forall alg . HashAlgorithm alg => HashAlg alg 41 42benchHash = 43 [ env oneKB $ \b -> bgroup "1KB" $ map (doHashBench b) hashAlgs 44 , env oneMB $ \b -> bgroup "1MB" $ map (doHashBench b) hashAlgs 45 ] 46 where 47 doHashBench b (name, HashAlg alg) = bench name $ nf (hashWith alg) b 48 49 oneKB :: IO Bytes 50 oneKB = getRandomBytes 1024 51 52 oneMB :: IO Bytes 53 oneMB = getRandomBytes $ 1024 * 1024 54 55 hashAlgs = 56 [ ("MD2", HashAlg MD2) 57 , ("MD4", HashAlg MD4) 58 , ("MD5", HashAlg MD5) 59 , ("SHA1", HashAlg SHA1) 60 , ("SHA224", HashAlg SHA224) 61 , ("SHA256", HashAlg SHA256) 62 , ("SHA384", HashAlg SHA384) 63 , ("SHA512", HashAlg SHA512) 64 , ("SHA512t_224", HashAlg SHA512t_224) 65 , ("SHA512t_256", HashAlg SHA512t_256) 66 , ("RIPEMD160", HashAlg RIPEMD160) 67 , ("Tiger", HashAlg Tiger) 68 --, ("Skein256-160", HashAlg Skein256_160) 69 , ("Skein256-256", HashAlg Skein256_256) 70 --, ("Skein512-160", HashAlg Skein512_160) 71 , ("Skein512-384", HashAlg Skein512_384) 72 , ("Skein512-512", HashAlg Skein512_512) 73 --, ("Skein512-896", HashAlg Skein512_896) 74 , ("Whirlpool", HashAlg Whirlpool) 75 , ("Keccak-224", HashAlg Keccak_224) 76 , ("Keccak-256", HashAlg Keccak_256) 77 , ("Keccak-384", HashAlg Keccak_384) 78 , ("Keccak-512", HashAlg Keccak_512) 79 , ("SHA3-224", HashAlg SHA3_224) 80 , ("SHA3-256", HashAlg SHA3_256) 81 , ("SHA3-384", HashAlg SHA3_384) 82 , ("SHA3-512", HashAlg SHA3_512) 83 , ("Blake2b-160", HashAlg Blake2b_160) 84 , ("Blake2b-224", HashAlg Blake2b_224) 85 , ("Blake2b-256", HashAlg Blake2b_256) 86 , ("Blake2b-384", HashAlg Blake2b_384) 87 , ("Blake2b-512", HashAlg Blake2b_512) 88 , ("Blake2s-160", HashAlg Blake2s_160) 89 , ("Blake2s-224", HashAlg Blake2s_224) 90 , ("Blake2s-256", HashAlg Blake2s_256) 91 ] 92 93benchPBKDF2 = 94 [ bgroup "64" 95 [ bench "cryptonite-PBKDF2-100-64" $ nf (pbkdf2 64) 100 96 , bench "cryptonite-PBKDF2-1000-64" $ nf (pbkdf2 64) 1000 97 , bench "cryptonite-PBKDF2-10000-64" $ nf (pbkdf2 64) 10000 98 ] 99 , bgroup "128" 100 [ bench "cryptonite-PBKDF2-100-128" $ nf (pbkdf2 128) 100 101 , bench "cryptonite-PBKDF2-1000-128" $ nf (pbkdf2 128) 1000 102 , bench "cryptonite-PBKDF2-10000-128" $ nf (pbkdf2 128) 10000 103 ] 104 ] 105 where 106 pbkdf2 :: Int -> Int -> B.ByteString 107 pbkdf2 n iter = PBKDF2.generate (PBKDF2.prfHMAC SHA512) (params n iter) mypass mysalt 108 109 mypass, mysalt :: B.ByteString 110 mypass = "password" 111 mysalt = "salt" 112 113 params n iter = PBKDF2.Parameters iter n 114 115benchBCrypt = 116 [ bench "cryptonite-BCrypt-4" $ nf bcrypt 4 117 , bench "cryptonite-BCrypt-5" $ nf bcrypt 5 118 , bench "cryptonite-BCrypt-7" $ nf bcrypt 7 119 , bench "cryptonite-BCrypt-11" $ nf bcrypt 11 120 ] 121 where 122 bcrypt :: Int -> B.ByteString 123 bcrypt cost = BCrypt.bcrypt cost mysalt mypass 124 125 mypass, mysalt :: B.ByteString 126 mypass = "password" 127 mysalt = "saltsaltsaltsalt" 128 129benchBlockCipher = 130 [ bgroup "ECB" benchECB 131 , bgroup "CBC" benchCBC 132 ] 133 where 134 benchECB = 135 [ bench "DES-input=1024" $ nf (run (undefined :: DES) cipherInit key8) input1024 136 , bench "Blowfish128-input=1024" $ nf (run (undefined :: Blowfish128) cipherInit key16) input1024 137 , bench "Twofish128-input=1024" $ nf (run (undefined :: Twofish128) cipherInit key16) input1024 138 , bench "CAST5-128-input=1024" $ nf (run (undefined :: CAST5) cipherInit key16) input1024 139 , bench "AES128-input=1024" $ nf (run (undefined :: AES128) cipherInit key16) input1024 140 , bench "AES256-input=1024" $ nf (run (undefined :: AES256) cipherInit key32) input1024 141 ] 142 where run :: (ByteArray ba, ByteArray key, BlockCipher c) 143 => c -> (key -> CryptoFailable c) -> key -> ba -> ba 144 run _witness initF key input = 145 (ecbEncrypt (throwCryptoError (initF key))) input 146 147 benchCBC = 148 [ bench "DES-input=1024" $ nf (run (undefined :: DES) cipherInit key8 iv8) input1024 149 , bench "Blowfish128-input=1024" $ nf (run (undefined :: Blowfish128) cipherInit key16 iv8) input1024 150 , bench "Twofish128-input=1024" $ nf (run (undefined :: Twofish128) cipherInit key16 iv16) input1024 151 , bench "CAST5-128-input=1024" $ nf (run (undefined :: CAST5) cipherInit key16 iv8) input1024 152 , bench "AES128-input=1024" $ nf (run (undefined :: AES128) cipherInit key16 iv16) input1024 153 , bench "AES256-input=1024" $ nf (run (undefined :: AES256) cipherInit key32 iv16) input1024 154 ] 155 where run :: (ByteArray ba, ByteArray key, BlockCipher c) 156 => c -> (key -> CryptoFailable c) -> key -> IV c -> ba -> ba 157 run _witness initF key iv input = 158 (cbcEncrypt (throwCryptoError (initF key))) iv input 159 160 key8 = B.replicate 8 0 161 key16 = B.replicate 16 0 162 key32 = B.replicate 32 0 163 input1024 = B.replicate 1024 0 164 165 iv8 :: BlockCipher c => IV c 166 iv8 = maybe (error "iv size 8") id $ makeIV key8 167 168 iv16 :: BlockCipher c => IV c 169 iv16 = maybe (error "iv size 16") id $ makeIV key16 170 171benchAE = 172 [ bench "ChaChaPoly1305" $ nf (cp key32) (input64, input1024) 173 , bench "AES-GCM" $ nf (gcm key32) (input64, input1024) 174 , bench "AES-CCM" $ nf (ccm key32) (input64, input1024) 175 , bench "AES-GCM-SIV" $ nf (gcmsiv key32) (input64, input1024) 176 ] 177 where cp k (ini, plain) = 178 let iniState = throwCryptoError $ CP.initialize k (throwCryptoError $ CP.nonce12 nonce12) 179 afterAAD = CP.finalizeAAD (CP.appendAAD ini iniState) 180 (out, afterEncrypt) = CP.encrypt plain afterAAD 181 outtag = CP.finalize afterEncrypt 182 in (outtag, out) 183 184 gcm k (ini, plain) = 185 let ctx = throwCryptoError (cipherInit k) :: AES256 186 state = throwCryptoError $ aeadInit AEAD_GCM ctx nonce12 187 in aeadSimpleEncrypt state ini plain 16 188 189 ccm k (ini, plain) = 190 let ctx = throwCryptoError (cipherInit k) :: AES256 191 mode = AEAD_CCM 1024 CCM_M16 CCM_L3 192 state = throwCryptoError $ aeadInit mode ctx nonce12 193 in aeadSimpleEncrypt state ini plain 16 194 195 gcmsiv k (ini, plain) = 196 let ctx = throwCryptoError (cipherInit k) :: AES256 197 iv = throwCryptoError (AESGCMSIV.nonce nonce12) 198 in AESGCMSIV.encrypt ctx iv ini plain 199 200 input64 = B.replicate 64 0 201 input1024 = B.replicate 1024 0 202 203 nonce12 :: B.ByteString 204 nonce12 = B.replicate 12 0 205 206 key32 = B.replicate 32 0 207 208benchECC = 209 [ bench "pointAddTwoMuls-baseline" $ nf run_b (n1, p1, n2, p2) 210 , bench "pointAddTwoMuls-optimized" $ nf run_o (n1, p1, n2, p2) 211 , bench "pointAdd-ECC" $ nf run_c (p1, p2) 212 , bench "pointMul-ECC" $ nf run_d (n1, p2) 213 ] 214 where run_b (n, p, k, q) = ECC.pointAdd c (ECC.pointMul c n p) 215 (ECC.pointMul c k q) 216 217 run_o (n, p, k, q) = ECC.pointAddTwoMuls c n p k q 218 run_c (p, q) = ECC.pointAdd c p q 219 run_d (n, p) = ECC.pointMul c n p 220 221 c = ECC.getCurveByName ECC.SEC_p256r1 222 p1 = ECC.pointBaseMul c n1 223 p2 = ECC.pointBaseMul c n2 224 n1 = 0x2ba9daf2363b2819e69b34a39cf496c2458a9b2a21505ea9e7b7cbca42dc7435 225 n2 = 0xf054a7f60d10b8c2cf847ee90e9e029f8b0e971b09ca5f55c4d49921a11fadc1 226 227benchP256 = 228 [ bench "pointAddTwoMuls-P256" $ nf run_p (n1, p1, n2, p2) 229 , bench "pointAdd-P256" $ nf run_q (p1, p2) 230 , bench "pointMul-P256" $ nf run_t (n1, p1) 231 ] 232 where run_p (n, p, k, q) = P256.pointAdd (P256.pointMul n p) (P256.pointMul k q) 233 run_q (p, q) = P256.pointAdd p q 234 run_t (n, p) = P256.pointMul n p 235 236 xS = 0xde2444bebc8d36e682edd27e0f271508617519b3221a8fa0b77cab3989da97c9 237 yS = 0xc093ae7ff36e5380fc01a5aad1e66659702de80f53cec576b6350b243042a256 238 xT = 0x55a8b00f8da1d44e62f6b3b25316212e39540dc861c89575bb8cf92e35e0986b 239 yT = 0x5421c3209c2d6c704835d82ac4c3dd90f61a8a52598b9e7ab656e9d8c8b24316 240 p1 = P256.pointFromIntegers (xS, yS) 241 p2 = P256.pointFromIntegers (xT, yT) 242 n1 = throwCryptoError $ P256.scalarFromInteger 0x2ba9daf2363b2819e69b34a39cf496c2458a9b2a21505ea9e7b7cbca42dc7435 243 n2 = throwCryptoError $ P256.scalarFromInteger 0xf054a7f60d10b8c2cf847ee90e9e029f8b0e971b09ca5f55c4d49921a11fadc1 244 245 246 247benchFFDH = map doFFDHBench primes 248 where 249 doFFDHBench (e, p) = 250 let bits = numBits p 251 params = DH.Params { DH.params_p = p, DH.params_g = 2, DH.params_bits = bits } 252 in env (generate e params) $ bench (show bits) . nf (run params) 253 254 generate e params = do 255 aPriv <- DH.PrivateNumber `fmap` generatePriv e 256 bPriv <- DH.PrivateNumber `fmap` generatePriv e 257 return (aPriv, DH.calculatePublic params bPriv) 258 259 generatePriv e = generateParams e (Just SetHighest) False 260 261 run params (priv, pub) = DH.getShared params priv pub 262 263 -- RFC 7919: prime p with minimal size of exponent 264 primes = [ (225, 0xFFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B423861285C97FFFFFFFFFFFFFFFF) 265 , (275, 0xFFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B66C62E37FFFFFFFFFFFFFFFF) 266 , (325, 0xFFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB7930E9E4E58857B6AC7D5F42D69F6D187763CF1D5503400487F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832A907600A918130C46DC778F971AD0038092999A333CB8B7A1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E655F6AFFFFFFFFFFFFFFFF) 267 , (375, 0xFFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB7930E9E4E58857B6AC7D5F42D69F6D187763CF1D5503400487F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832A907600A918130C46DC778F971AD0038092999A333CB8B7A1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD9020BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA63BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3ACDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477A52471F7A9A96910B855322EDB6340D8A00EF092350511E30ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538CD72B03746AE77F5E62292C311562A846505DC82DB854338AE49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B045B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1A41D570D7938DAD4A40E329CD0E40E65FFFFFFFFFFFFFFFF) 268 , (400, 0xFFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB7930E9E4E58857B6AC7D5F42D69F6D187763CF1D5503400487F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832A907600A918130C46DC778F971AD0038092999A333CB8B7A1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD9020BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA63BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3ACDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477A52471F7A9A96910B855322EDB6340D8A00EF092350511E30ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538CD72B03746AE77F5E62292C311562A846505DC82DB854338AE49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B045B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1A41D570D7938DAD4A40E329CCFF46AAA36AD004CF600C8381E425A31D951AE64FDB23FCEC9509D43687FEB69EDD1CC5E0B8CC3BDF64B10EF86B63142A3AB8829555B2F747C932665CB2C0F1CC01BD70229388839D2AF05E454504AC78B7582822846C0BA35C35F5C59160CC046FD8251541FC68C9C86B022BB7099876A460E7451A8A93109703FEE1C217E6C3826E52C51AA691E0E423CFC99E9E31650C1217B624816CDAD9A95F9D5B8019488D9C0A0A1FE3075A577E23183F81D4A3F2FA4571EFC8CE0BA8A4FE8B6855DFE72B0A66EDED2FBABFBE58A30FAFABE1C5D71A87E2F741EF8C1FE86FEA6BBFDE530677F0D97D11D49F7A8443D0822E506A9F4614E011E2A94838FF88CD68C8BB7C5C6424CFFFFFFFFFFFFFFFF) 269 ] 270 271data CurveDH = forall c . (EllipticCurveDH c, NFData (Scalar c), NFData (Point c)) => CurveDH c 272 273benchECDH = map doECDHBench curves 274 where 275 doECDHBench (name, CurveDH c) = 276 let proxy = Just c -- using Maybe as Proxy 277 in env (generate proxy) $ bench name . nf (run proxy) 278 279 generate proxy = do 280 KeyPair _ aScalar <- curveGenerateKeyPair proxy 281 KeyPair bPoint _ <- curveGenerateKeyPair proxy 282 return (aScalar, bPoint) 283 284 run proxy (s, p) = throwCryptoError (ecdh proxy s p) 285 286 curves = [ ("P256R1", CurveDH Curve_P256R1) 287 , ("P384R1", CurveDH Curve_P384R1) 288 , ("P521R1", CurveDH Curve_P521R1) 289 , ("X25519", CurveDH Curve_X25519) 290 , ("X448", CurveDH Curve_X448) 291 ] 292 293data CurveHashECDSA = 294 forall curve hashAlg . (ECDSA.EllipticCurveECDSA curve, 295 NFData (Scalar curve), 296 NFData (Point curve), 297 HashAlgorithm hashAlg) => CurveHashECDSA curve hashAlg 298 299benchECDSA = map doECDSABench curveHashes 300 where 301 doECDSABench (name, CurveHashECDSA c hashAlg) = 302 let proxy = Just c -- using Maybe as Proxy 303 in bgroup name 304 [ env (signGenerate proxy) $ bench "sign" . nfIO . signRun proxy hashAlg 305 , env (verifyGenerate proxy hashAlg) $ bench "verify" . nf (verifyRun proxy hashAlg) 306 ] 307 308 signGenerate proxy = do 309 m <- tenKB 310 s <- curveGenerateScalar proxy 311 return (s, m) 312 313 signRun proxy hashAlg (priv, msg) = ECDSA.sign proxy priv hashAlg msg 314 315 verifyGenerate proxy hashAlg = do 316 m <- tenKB 317 KeyPair p s <- curveGenerateKeyPair proxy 318 sig <- ECDSA.sign proxy s hashAlg m 319 return (p, sig, m) 320 321 verifyRun proxy hashAlg (pub, sig, msg) = ECDSA.verify proxy hashAlg pub sig msg 322 323 tenKB :: IO Bytes 324 tenKB = getRandomBytes 10240 325 326 curveHashes = [ ("secp256r1_sha256", CurveHashECDSA Curve_P256R1 SHA256) 327 , ("secp384r1_sha384", CurveHashECDSA Curve_P384R1 SHA384) 328 , ("secp521r1_sha512", CurveHashECDSA Curve_P521R1 SHA512) 329 ] 330 331benchEdDSA = 332 [ bgroup "EdDSA-Ed25519" benchGenEd25519 333 , bgroup "Ed25519" benchEd25519 334 ] 335 where 336 benchGen prx alg = 337 [ bench "sign" $ perBatchEnv (genEnv prx alg) (run_gen_sign prx) 338 , bench "verify" $ perBatchEnv (genEnv prx alg) (run_gen_verify prx) 339 ] 340 341 benchGenEd25519 = benchGen (Just Curve_Edwards25519) SHA512 342 benchEd25519 = 343 [ bench "sign" $ perBatchEnv ed25519Env run_ed25519_sign 344 , bench "verify" $ perBatchEnv ed25519Env run_ed25519_verify 345 ] 346 347 msg = B.empty -- empty message = worst-case scenario showing API overhead 348 349 genEnv prx alg _ = do 350 sec <- EdDSA.generateSecretKey prx 351 let pub = EdDSA.toPublic prx alg sec 352 sig = EdDSA.sign prx sec pub msg 353 return (sec, pub, sig) 354 355 run_gen_sign prx (sec, pub, _) = return (EdDSA.sign prx sec pub msg) 356 357 run_gen_verify prx (_, pub, sig) = return (EdDSA.verify prx pub msg sig) 358 359 ed25519Env _ = do 360 sec <- Ed25519.generateSecretKey 361 let pub = Ed25519.toPublic sec 362 sig = Ed25519.sign sec pub msg 363 return (sec, pub, sig) 364 365 run_ed25519_sign (sec, pub, _) = return (Ed25519.sign sec pub msg) 366 367 run_ed25519_verify (_, pub, sig) = return (Ed25519.verify pub msg sig) 368 369main = defaultMain 370 [ bgroup "hash" benchHash 371 , bgroup "block-cipher" benchBlockCipher 372 , bgroup "AE" benchAE 373 , bgroup "pbkdf2" benchPBKDF2 374 , bgroup "bcrypt" benchBCrypt 375 , bgroup "ECC" benchECC 376 , bgroup "P256" benchP256 377 , bgroup "DH" 378 [ bgroup "FFDH" benchFFDH 379 , bgroup "ECDH" benchECDH 380 ] 381 , bgroup "ECDSA" benchECDSA 382 , bgroup "EdDSA" benchEdDSA 383 , bgroup "F2m" benchF2m 384 ] 385