| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 
 | {-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts #-}
module ECDSA (tests) where
import qualified Crypto.ECC as ECDSA
import qualified Crypto.PubKey.ECC.ECDSA as ECC
import qualified Crypto.PubKey.ECC.Types as ECC
import qualified Crypto.PubKey.ECDSA as ECDSA
import Crypto.Hash.Algorithms
import Crypto.Error
import qualified Data.ByteString as B
import Imports
data Curve = forall curve. (ECDSA.EllipticCurveECDSA curve, Show (ECDSA.Scalar curve)) => Curve curve ECC.Curve ECC.CurveName
instance Show Curve where
    showsPrec d (Curve _ _ name) = showsPrec d name
instance Arbitrary Curve where
    arbitrary = elements
        [ makeCurve ECDSA.Curve_P256R1 ECC.SEC_p256r1
        , makeCurve ECDSA.Curve_P384R1 ECC.SEC_p384r1
        , makeCurve ECDSA.Curve_P521R1 ECC.SEC_p521r1
        ]
      where
        makeCurve c name = Curve c (ECC.getCurveByName name) name
arbitraryScalar curve = choose (1, n - 1)
  where n = ECC.ecc_n (ECC.common_curve curve)
sigECCToECDSA :: ECDSA.EllipticCurveECDSA curve
              => proxy curve -> ECC.Signature -> ECDSA.Signature curve
sigECCToECDSA prx (ECC.Signature r s) =
    ECDSA.Signature (throwCryptoError $ ECDSA.scalarFromInteger prx r)
                    (throwCryptoError $ ECDSA.scalarFromInteger prx s)
tests = localOption (QuickCheckTests 5) $ testGroup "ECDSA"
    [ testProperty "SHA1"   $ propertyECDSA SHA1
    , testProperty "SHA224" $ propertyECDSA SHA224
    , testProperty "SHA256" $ propertyECDSA SHA256
    , testProperty "SHA384" $ propertyECDSA SHA384
    , testProperty "SHA512" $ propertyECDSA SHA512
    ]
  where
    propertyECDSA hashAlg (Curve c curve _) (ArbitraryBS0_2901 msg) = do
        d    <- arbitraryScalar curve
        kECC <- arbitraryScalar curve
        let privECC   = ECC.PrivateKey curve d
            prx       = Just c -- using Maybe as Proxy
            kECDSA    = throwCryptoError $ ECDSA.scalarFromInteger prx kECC
            privECDSA = throwCryptoError $ ECDSA.scalarFromInteger prx d
            pubECDSA  = ECDSA.toPublic prx privECDSA
            Just sigECC   = ECC.signWith kECC privECC hashAlg msg
            Just sigECDSA = ECDSA.signWith prx kECDSA privECDSA hashAlg msg
            sigECDSA' = sigECCToECDSA prx sigECC
            msg' = msg `B.append` B.singleton 42
        return $ propertyHold [ eqTest "signature" sigECDSA sigECDSA'
                              , eqTest "verification" True (ECDSA.verify prx hashAlg pubECDSA sigECDSA' msg)
                              , eqTest "alteration"  False (ECDSA.verify prx hashAlg pubECDSA sigECDSA msg')
                              ]
 |