packages feed

secp256k1-0.4.2: haskell/test/Crypto/Secp256k1/Tests.hs

module Crypto.Secp256k1.Tests (tests) where

import           Crypto.Secp256k1
import qualified Data.ByteString.Base16               as B16
import qualified Data.ByteString.Char8                as B8
import           Data.Maybe                           (fromMaybe)
import           Data.String                          (fromString)
import           Data.String.Conversions              (cs)
import           Test.Framework                       (Test, testGroup)
import           Test.Framework.Providers.HUnit       (testCase)
import           Test.Framework.Providers.QuickCheck2 (testProperty)
import           Test.HUnit                           (Assertion, assertEqual)

tests :: [Test]
tests =
    [ testGroup "Signing"
        [ testProperty "Signing messages" signMsgTest
        , testProperty "Bad signatures" badSignatureTest
        , testProperty "Normalize signatures" normalizeSigTest
        ]
    , testGroup "Serialization"
        [ testProperty "Serialize public key" serializePubKeyTest
        , testProperty "Serialize DER signature" serializeSigTest
        , testProperty "Serialize lax DER signature" serializeLaxSigTest
        , testProperty "Serialize compact signature" serializeCompactSigTest
        , testProperty "Serialize secret key" serializeSecKeyTest
        , testProperty "Show/Read public key" (showRead :: PubKey -> Bool)
        , testProperty "Show/Read secret key" (showRead :: SecKey -> Bool)
        , testProperty "Show/Read tweak" (showReadTweak :: SecKey -> Bool)
        , testProperty "Show/Read signature" (showReadSig :: (SecKey, Msg) -> Bool)
        , testProperty "Show/Read message" (showRead :: Msg -> Bool)
        , testProperty "String public key" isStringPubKey
        , testProperty "String secret key" isStringSecKey
        , testProperty "String signature" isStringSig
        , testProperty "String message" isStringMsg
        , testProperty "String tweak" isStringTweak
        ]
    , testGroup "Tweaks"
        [ testCase "Tweak add secret key" tweakAddSecKeyTest
        , testCase "Tweak multiply secret key" tweakMulSecKeyTest
        , testCase "Tweak add public key" tweakAddPubKeyTest
        , testCase "Tweak multiply public key" tweakMulPubKeyTest
        , testCase "Combine public keys" combinePubKeyTest
        ]
    ]

isStringPubKey :: (PubKey, Bool) -> Bool
isStringPubKey (k, c) = k == fromString (cs hex) where
    hex = B16.encode $ exportPubKey c k

isStringSig :: (SecKey, Msg) -> Bool
isStringSig (k, m) = g == fromString (cs hex) where
    g = signMsg k m
    hex = B16.encode $ exportSig g

isStringMsg :: Msg -> Bool
isStringMsg m = m == fromString (cs m') where
    m' = B16.encode $ getMsg m

isStringSecKey :: SecKey -> Bool
isStringSecKey k = k == fromString (cs hex) where
    hex = B16.encode $ getSecKey k

isStringTweak :: SecKey -> Bool
isStringTweak k = t == fromString (cs hex) where
    t = fromMaybe e . tweak $ getSecKey k
    hex = B16.encode $ getTweak t
    e = error "Could not extract tweak from secret key"

showReadTweak :: SecKey -> Bool
showReadTweak k = showRead t where
    t = tweak $ getSecKey k

showReadSig :: (SecKey, Msg) -> Bool
showReadSig (k, m) = showRead sig where
    sig = signMsg k m

showRead :: (Show a, Read a, Eq a) => a -> Bool
showRead x = read (show x) == x

signMsgTest :: (Msg, SecKey) -> Bool
signMsgTest (fm, fk) = verifySig fp fg fm where
    fp = derivePubKey fk
    fg = signMsg fk fm

badSignatureTest :: (Msg, SecKey, PubKey) -> Bool
badSignatureTest (fm, fk, fp) = not $ verifySig fp fg fm where
    fg = signMsg fk fm

normalizeSigTest :: (Msg, SecKey) -> Bool
normalizeSigTest (fm, fk) = not norm && sig == fg where
    fg = signMsg fk fm
    (sig, norm) = normalizeSig fg

serializePubKeyTest :: (PubKey, Bool) -> Bool
serializePubKeyTest (fp, b) =
    case importPubKey $ exportPubKey b fp of
        Just fp' -> fp == fp'
        Nothing -> False

serializeSigTest :: (Msg, SecKey) -> Bool
serializeSigTest (fm, fk) =
    case importSig $ exportSig fg of
        Just fg' -> fg == fg'
        Nothing -> False
  where
    fg = signMsg fk fm

serializeLaxSigTest :: (Msg, SecKey) -> Bool
serializeLaxSigTest (fm, fk) =
    case laxImportSig $ exportSig fg of
        Just fg' -> fg == fg'
        Nothing -> False
  where
    fg = signMsg fk fm

serializeCompactSigTest :: (Msg, SecKey) -> Bool
serializeCompactSigTest (fm, fk) =
    case importCompactSig $ exportCompactSig fg of
        Just fg' -> fg == fg'
        Nothing -> False
  where
    fg = signMsg fk fm

serializeSecKeyTest :: SecKey -> Bool
serializeSecKeyTest fk =
    case secKey $ getSecKey fk of
        Just fk' -> fk == fk'
        Nothing -> False

tweakAddSecKeyTest :: Assertion
tweakAddSecKeyTest =
    assertEqual "tweaked keys match" expected tweaked
  where
    tweaked = do
        key <- secKey $ fst $ B16.decode $ B8.pack
            "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"
        twk <- tweak $ fst $ B16.decode $ B8.pack
            "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"
        tweakAddSecKey key twk
    expected = secKey $ fst $ B16.decode $ B8.pack
        "ec1e3ce1cefa18a671d51125e2b249688d934b0e28f5d1665384d9b02f929059"

tweakMulSecKeyTest :: Assertion
tweakMulSecKeyTest =
    assertEqual "tweaked keys match" expected tweaked
  where
    tweaked = do
        key <- secKey $ fst $ B16.decode $ B8.pack
            "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"
        twk <- tweak $ fst $ B16.decode $ B8.pack
            "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"
        tweakMulSecKey key twk
    expected = secKey $ fst $ B16.decode $ B8.pack
        "a96f5962493acb179f60a86a9785fc7a30e0c39b64c09d24fe064d9aef15e4c0"

tweakAddPubKeyTest :: Assertion
tweakAddPubKeyTest =
    assertEqual "tweaked keys match" expected tweaked
  where
    tweaked = do
        pub <- importPubKey $ fst $ B16.decode $ B8.pack
            "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd44705\
            \12213d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"
        twk <- tweak $ fst $ B16.decode $ B8.pack
            "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"
        tweakAddPubKey pub twk
    expected = importPubKey $ fst $ B16.decode $ B8.pack
        "04441c3982b97576646e0df0c96736063df6b42f2ee566d13b9f6424302d1379e518fd\
        \c87a14c5435bff7a5db4552042cb4120c6b86a4bbd3d0643f3c14ad01368"

tweakMulPubKeyTest :: Assertion
tweakMulPubKeyTest =
    assertEqual "tweaked keys match" expected tweaked
  where
    tweaked = do
        pub <- importPubKey $ fst $ B16.decode $ B8.pack
            "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd44705\
            \12213d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"
        twk <- tweak $ fst $ B16.decode $ B8.pack
            "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"
        tweakMulPubKey pub twk
    expected = importPubKey $ fst $ B16.decode $ B8.pack
        "04f379dc99cdf5c83e433defa267fbb3377d61d6b779c06a0e4ce29ae3ff5353b12ae4\
        \9c9d07e7368f2ba5a446c203255ce912322991a2d6a9d5d5761c61ed1845"

combinePubKeyTest :: Assertion
combinePubKeyTest =
    assertEqual "combined keys match" expected combined
  where
    combined = do
        pub1 <- importPubKey $ fst $ B16.decode $ B8.pack
            "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd44705\
            \12213d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"
        pub2 <- importPubKey $ fst $ B16.decode $ B8.pack
            "0487d82042d93447008dfe2af762068a1e53ff394a5bf8f68a045fa642b99ea5d1\
            \53f577dd2dba6c7ae4cfd7b6622409d7edd2d76dd13a8092cd3af97b77bd2c77"
        pub3 <- importPubKey $ fst $ B16.decode $ B8.pack
            "049b101edcbe1ee37ff6b2318526a425b629e823d7d8d9154417880595a28000ee\
            \3febd908754b8ce4e491aa6fe488b41fb5d4bb3788e33c9ff95a7a9229166d59"
        combinePubKeys [pub1, pub2, pub3]
    expected = importPubKey $ fst $ B16.decode $ B8.pack
        "043d9a7ec70011efc23c33a7e62d2ea73cca87797e3b659d93bea6aa871aebde56c3bc\
        \6134ca82e324b0ab9c0e601a6d2933afe7fb5d9f3aae900f5c5dc6e362c8"