packages feed

libsecp256k1 0.0.3 → 0.1.0

raw patch · 11 files changed

+1106/−807 lines, 11 filesdep +entropydep +hedgehogdep +libsecp256k1dep −monad-pardep −mtldep −secp256k1-haskelldep ~memorydep ~transformersPVP ok

version bump matches the API change (PVP)

Dependencies added: entropy, hedgehog, libsecp256k1

Dependencies removed: monad-par, mtl, secp256k1-haskell

Dependency ranges changed: memory, transformers

API changes (from Hackage documentation)

- Crypto.Secp256k1: SchnorrExtra :: (ByteString -> SecKey -> PubKeyXO -> ByteString -> a -> Maybe (SizedByteArray 32 ByteString)) -> a -> SchnorrExtra a
- Crypto.Secp256k1: [schnorrExtraData] :: SchnorrExtra a -> a
- Crypto.Secp256k1: [schnorrExtraNonceFunHardened] :: SchnorrExtra a -> ByteString -> SecKey -> PubKeyXO -> ByteString -> a -> Maybe (SizedByteArray 32 ByteString)
- Crypto.Secp256k1: data SchnorrExtra a
- Crypto.Secp256k1: ecSecKeyTweakAdd :: SecKey -> Tweak -> Maybe SecKey
- Crypto.Secp256k1: ecSecKeyTweakMul :: SecKey -> Tweak -> Maybe SecKey
- Crypto.Secp256k1: schnorrSignCustom :: forall a. KeyPair -> ByteString -> SchnorrExtra a -> Maybe Signature
- Paths_libsecp256k1: getBinDir :: IO FilePath
- Paths_libsecp256k1: getDataDir :: IO FilePath
- Paths_libsecp256k1: getDataFileName :: FilePath -> IO FilePath
- Paths_libsecp256k1: getDynLibDir :: IO FilePath
- Paths_libsecp256k1: getLibDir :: IO FilePath
- Paths_libsecp256k1: getLibexecDir :: IO FilePath
- Paths_libsecp256k1: getSysconfDir :: IO FilePath
- Paths_libsecp256k1: version :: Version
+ Crypto.Secp256k1: exportSecKey :: SecKey -> ByteString
+ Crypto.Secp256k1: instance GHC.Show.Show Crypto.Secp256k1.PubKeyXO
+ Crypto.Secp256k1: instance GHC.Show.Show Crypto.Secp256k1.PubKeyXY
+ Crypto.Secp256k1: instance GHC.Show.Show Crypto.Secp256k1.RecoverableSignature
+ Crypto.Secp256k1: instance GHC.Show.Show Crypto.Secp256k1.SecKey
+ Crypto.Secp256k1: instance GHC.Show.Show Crypto.Secp256k1.Signature
+ Crypto.Secp256k1: instance GHC.Show.Show Crypto.Secp256k1.Tweak
+ Crypto.Secp256k1: keyPairSecKey :: KeyPair -> SecKey
+ Crypto.Secp256k1: secKeyTweakAdd :: SecKey -> Tweak -> Maybe SecKey
+ Crypto.Secp256k1: secKeyTweakMul :: SecKey -> Tweak -> Maybe SecKey
+ Crypto.Secp256k1.Gen: keyPairGen :: MonadGen m => m KeyPair
+ Crypto.Secp256k1.Gen: pubKeyXOGen :: MonadGen m => m PubKeyXO
+ Crypto.Secp256k1.Gen: pubKeyXYGen :: MonadGen m => m PubKeyXY
+ Crypto.Secp256k1.Gen: secKeyGen :: MonadGen m => m SecKey
+ Crypto.Secp256k1.Gen: tweakGen :: MonadGen m => m Tweak
+ Crypto.Secp256k1.Internal: decodeBase16 :: ByteString -> Either String ByteString
+ Crypto.Secp256k1.Internal: encodeBase16 :: ByteString -> ByteString

Files

libsecp256k1.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           libsecp256k1-version:        0.0.3+version:        0.1.0 synopsis:       Bindings for secp256k1 description:    Sign and verify signatures using the secp256k1 library. category:       Crypto@@ -28,6 +28,7 @@ library   exposed-modules:       Crypto.Secp256k1+      Crypto.Secp256k1.Gen       Crypto.Secp256k1.Internal       Crypto.Secp256k1.Prim   other-modules:@@ -39,16 +40,21 @@   build-depends:       base >=4.9 && <5     , bytestring >=0.10.8 && <0.12-    , memory-    , transformers+    , entropy >=0.3.8 && <0.5+    , hedgehog+    , memory >=0.14.15 && <1.0+    , transformers >=0.4.0.0 && <1.0   default-language: Haskell2010  test-suite spec   type: exitcode-stdio-1.0-  main-is: Spec.hs+  main-is: Main.hs   other-modules:       Crypto.Secp256k1.PrimSpec+      Crypto.Secp256k1Prop       Crypto.Secp256k1Spec+      Spec+      Util       Paths_libsecp256k1   hs-source-dirs:       test@@ -57,11 +63,10 @@       HUnit     , base >=4.9 && <5     , bytestring >=0.10.8 && <0.12+    , entropy >=0.3.8 && <0.5+    , hedgehog     , hspec-    , memory-    , monad-par-    , mtl-    , secp256k1-haskell-    , transformers+    , libsecp256k1+    , memory >=0.14.15 && <1.0+    , transformers >=0.4.0.0 && <1.0   default-language: Haskell2010-  build-tool-depends: hspec-discover:hspec-discover
src/Crypto/Secp256k1.hs view
@@ -1,8 +1,6 @@ {-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE RankNTypes #-}@@ -32,6 +30,7 @@      -- * Parsing and Serialization     importSecKey,+    exportSecKey,     importPubKeyXY,     exportPubKeyXY,     importPubKeyXO,@@ -53,13 +52,14 @@     recSigToSig,     derivePubKey,     keyPairCreate,+    keyPairSecKey,     keyPairPubKeyXY,     keyPairPubKeyXO,     xyToXO,      -- * Tweaks-    ecSecKeyTweakAdd,-    ecSecKeyTweakMul,+    secKeyTweakAdd,+    secKeyTweakMul,     keyPairPubKeyXOTweakAdd,     pubKeyCombine,     pubKeyNegate,@@ -71,8 +71,6 @@      -- * Schnorr Operations     schnorrSign,-    SchnorrExtra (..),-    schnorrSignCustom,     schnorrVerify,      -- * Other@@ -86,6 +84,7 @@ import Crypto.Secp256k1.Internal import Crypto.Secp256k1.Prim (flagsEcUncompressed) import qualified Crypto.Secp256k1.Prim as Prim+import qualified Data.ByteArray.Encoding as BA import Data.ByteArray.Sized import Data.ByteString (ByteString) import qualified Data.ByteString as BS@@ -100,6 +99,7 @@  -- import Data.String.Conversions (ConvertibleStrings, cs) +import qualified Data.ByteString.Char8 as B8 import Data.Foldable (for_) import Data.Memory.PtrMethods (memCompare) import Foreign (@@ -108,6 +108,8 @@     FunPtr,     Ptr,     Storable,+    Word32,+    Word64,     Word8,     alloca,     allocaArray,@@ -135,6 +137,7 @@     withForeignPtr,  ) import Foreign.C (CInt (..), CSize (..))+import Foreign.Storable (Storable (..)) import GHC.Generics (Generic) import GHC.IO.Handle.Text (memcpy) import System.IO.Unsafe (unsafePerformIO)@@ -147,7 +150,16 @@  )  +-- | Secret Key newtype SecKey = SecKey {secKeyFPtr :: ForeignPtr Prim.Seckey32}+++instance Show SecKey where+    show SecKey{..} = unsafePerformIO . evalContT $ do+        secKeyPtr <- ContT (withForeignPtr secKeyFPtr)+        -- avoid allocating a new bytestring because we are only reading from this pointer+        bs <- lift (Data.ByteString.Unsafe.unsafePackCStringLen (castPtr secKeyPtr, 32))+        pure $ "0x" <> B8.unpack (BA.convertToBase BA.Base16 bs) instance Eq SecKey where     sk == sk' = unsafePerformIO . evalContT $ do         skp <- ContT $ withForeignPtr (secKeyFPtr sk)@@ -160,7 +172,14 @@         lift (memCompare (castPtr skp) (castPtr skp') 32)  +-- | Public Key with both X and Y coordinates newtype PubKeyXY = PubKeyXY {pubKeyXYFPtr :: ForeignPtr Prim.Pubkey64}+++instance Show PubKeyXY where+    show pk = "0x" <> B8.unpack (BA.convertToBase BA.Base16 (exportPubKeyXY True pk))++ instance Eq PubKeyXY where     pk == pk' = unsafePerformIO . evalContT $ do         pkp <- ContT . withForeignPtr . pubKeyXYFPtr $ pk@@ -175,7 +194,14 @@         pure $ compare res 0  +-- | Public Key with only an X coordinate. newtype PubKeyXO = PubKeyXO {pubKeyXOFPtr :: ForeignPtr Prim.XonlyPubkey64}+++instance Show PubKeyXO where+    show pk = "0x" <> B8.unpack (BA.convertToBase BA.Base16 (exportPubKeyXO pk))++ instance Eq PubKeyXO where     pk == pk' = unsafePerformIO . evalContT $ do         pkp <- ContT . withForeignPtr . pubKeyXOFPtr $ pk@@ -190,7 +216,10 @@         pure $ compare res 0  +-- | Structure containing information equivalent to 'SecKey' and 'PubKeyXY' newtype KeyPair = KeyPair {keyPairFPtr :: ForeignPtr Prim.Keypair96}++ instance Eq KeyPair where     kp == kp' = unsafePerformIO . evalContT $ do         kpp <- ContT $ withForeignPtr (keyPairFPtr kp)@@ -198,7 +227,12 @@         (EQ ==) <$> lift (memCompare (castPtr kpp) (castPtr kpp') 32)  +-- | Structure containing Signature (R,S) data. newtype Signature = Signature {signatureFPtr :: ForeignPtr Prim.Sig64}+++instance Show Signature where+    show sig = "0x" <> (B8.unpack . encodeBase16) (exportSignatureCompact sig) instance Eq Signature where     sig == sig' = unsafePerformIO . evalContT $ do         sigp <- ContT $ withForeignPtr (signatureFPtr sig)@@ -206,7 +240,14 @@         (EQ ==) <$> lift (memCompare (castPtr sigp) (castPtr sigp') 32)  +-- | Structure containing Signature AND recovery ID newtype RecoverableSignature = RecoverableSignature {recoverableSignatureFPtr :: ForeignPtr Prim.RecSig65}+++instance Show RecoverableSignature where+    show recSig = "0x" <> (B8.unpack . encodeBase16) (exportRecoverableSignature recSig)++ instance Eq RecoverableSignature where     rs == rs' = unsafePerformIO . evalContT $ do         rsp <- ContT $ withForeignPtr (recoverableSignatureFPtr rs)@@ -214,7 +255,14 @@         (EQ ==) <$> lift (memCompare (castPtr rsp) (castPtr rsp') 32)  +-- | Isomorphic to 'SecKey' but specifically used for tweaking (EC Group operations) other keys newtype Tweak = Tweak {tweakFPtr :: ForeignPtr Prim.Tweak32}+++instance Show Tweak where+    show (Tweak fptr) = show (SecKey $ castForeignPtr fptr)++ instance Eq Tweak where     sk == sk' = unsafePerformIO . evalContT $ do         skp <- ContT $ withForeignPtr (tweakFPtr sk)@@ -248,29 +296,39 @@                 else pure Nothing  +exportSecKey :: SecKey -> ByteString+exportSecKey SecKey{..} = unsafePerformIO . evalContT $ do+    secKeyPtr <- ContT (withForeignPtr secKeyFPtr)+    lift $ packByteString (secKeyPtr, 32)++ -- | Parses a 33 or 65 byte 'PubKeyXY', all other lengths will result in @Nothing@ importPubKeyXY :: ByteString -> Maybe PubKeyXY-importPubKeyXY bs = unsafePerformIO $-    unsafeUseByteString bs $ \(input, len) -> do-        pubkeyOutputBuf <- mallocBytes 64+importPubKeyXY bs = unsafePerformIO . evalContT $ do+    (input, len) <- ContT (unsafeUseByteString bs)+    lift $ do         if len == 33 || len == 65             then do-                ret <- Prim.ecPubkeyParse ctx (castPtr pubkeyOutputBuf) input len+                pubkeyOutputBuf <- mallocBytes 64+                ret <- Prim.ecPubkeyParse ctx pubkeyOutputBuf input len                 if isSuccess ret-                    then Just . PubKeyXY <$> newForeignPtr finalizerFree (castPtr pubkeyOutputBuf)+                    then Just . PubKeyXY <$> newForeignPtr finalizerFree pubkeyOutputBuf                     else free pubkeyOutputBuf $> Nothing             else pure Nothing   -- | Serialize 'PubKeyXY'. First argument @True@ for compressed output (33 bytes), @False@ for uncompressed (65 bytes). exportPubKeyXY :: Bool -> PubKeyXY -> ByteString-exportPubKeyXY compress (PubKeyXY fptr) = unsafePerformIO $ do+exportPubKeyXY compress PubKeyXY{..} = unsafePerformIO . evalContT $ do     let flags = if compress then Prim.flagsEcCompressed else Prim.flagsEcUncompressed     let sz = if compress then 33 else 65-    buf <- mallocBytes sz-    alloca $ \written -> do+    ptr <- ContT (withForeignPtr pubKeyXYFPtr)+    written <- ContT alloca+    lift $ do+        poke written (fromIntegral sz)+        buf <- mallocBytes sz         -- always succeeds so we don't need to check-        _ret <- withForeignPtr fptr $ \ptr -> Prim.ecPubkeySerialize ctx buf written ptr flags+        _ret <- Prim.ecPubkeySerialize ctx buf written ptr flags         len <- peek written         unsafePackMallocCStringLen (castPtr buf, fromIntegral len) @@ -286,7 +344,7 @@             ret <- Prim.xonlyPubkeyParse ctx outBuf ptr             if isSuccess ret                 then Just . PubKeyXO <$> newForeignPtr finalizerFree outBuf-                else pure Nothing+                else free outBuf $> Nothing   -- | Serializes 'PubKeyXO' to 32 byte @ByteString@@@ -307,11 +365,11 @@                     -- compact                     | len == 64 -> Prim.ecdsaSignatureParseCompact ctx outBuf inBuf                     -- der-                    | len >= 71 && len <= 73 -> Prim.ecdsaSignatureParseDer ctx outBuf inBuf len+                    | len >= 69 && len <= 73 -> Prim.ecdsaSignatureParseDer ctx outBuf inBuf len                     -- invalid                     | otherwise -> pure 0         if isSuccess ret-            then Just . Signature <$> newForeignPtr finalizerFree (castPtr outBuf)+            then Just . Signature <$> newForeignPtr finalizerFree outBuf             else free outBuf $> Nothing  @@ -330,6 +388,7 @@     -- as of Q4'2015 73 byte sigs became nonstandard so we will never create one that big     outBuf <- mallocBytes 72     alloca $ \written -> do+        poke written 72         -- always succeeds         _ret <- withForeignPtr fptr $ Prim.ecdsaSignatureSerializeDer ctx outBuf written         len <- peek written@@ -361,6 +420,7 @@         recIdPtr <- malloc         _ret <- Prim.ecdsaRecoverableSignatureSerializeCompact ctx outBuf recIdPtr recSigPtr         recId <- peek recIdPtr+        pokeByteOff outBuf 64 recId         unsafePackByteString (outBuf, 65)  @@ -383,16 +443,15 @@ ecdsaSign :: SecKey -> ByteString -> Maybe Signature ecdsaSign (SecKey skFPtr) msgHash     | BS.length msgHash /= 32 = Nothing-    | otherwise = unsafePerformIO $-        evalContT $ do-            skPtr <- ContT (withForeignPtr skFPtr)-            (msgHashPtr, _) <- ContT (unsafeUseByteString msgHash)-            sigBuf <- lift $ mallocBytes 64-            ret <- lift $ Prim.ecdsaSign ctx sigBuf msgHashPtr skPtr Prim.nonceFunctionDefault nullPtr-            lift $-                if isSuccess ret-                    then Just . Signature <$> newForeignPtr finalizerFree sigBuf-                    else free sigBuf $> Nothing+    | otherwise = unsafePerformIO . evalContT $ do+        skPtr <- ContT (withForeignPtr skFPtr)+        (msgHashPtr, _) <- ContT (unsafeUseByteString msgHash)+        lift $ do+            sigBuf <- mallocBytes 64+            ret <- Prim.ecdsaSign ctx sigBuf msgHashPtr skPtr Prim.nonceFunctionDefault nullPtr+            if isSuccess ret+                then Just . Signature <$> newForeignPtr finalizerFree sigBuf+                else free sigBuf $> Nothing   -- | Signs @ByteString@ with 'SecKey' only if @ByteString@ is 32 bytes. Retains ability to compute 'PubKeyXY' from the@@ -464,8 +523,8 @@   -- -- | Add 'Tweak' to 'SecKey'.-ecSecKeyTweakAdd :: SecKey -> Tweak -> Maybe SecKey-ecSecKeyTweakAdd SecKey{..} Tweak{..} = unsafePerformIO . evalContT $ do+secKeyTweakAdd :: SecKey -> Tweak -> Maybe SecKey+secKeyTweakAdd SecKey{..} Tweak{..} = unsafePerformIO . evalContT $ do     skPtr <- ContT (withForeignPtr secKeyFPtr)     skOut <- lift (mallocBytes 32)     lift (memcpy skOut skPtr 32)@@ -478,8 +537,8 @@   -- | Multiply 'SecKey' by 'Tweak'.-ecSecKeyTweakMul :: SecKey -> Tweak -> Maybe SecKey-ecSecKeyTweakMul SecKey{..} Tweak{..} = unsafePerformIO . evalContT $ do+secKeyTweakMul :: SecKey -> Tweak -> Maybe SecKey+secKeyTweakMul SecKey{..} Tweak{..} = unsafePerformIO . evalContT $ do     skPtr <- ContT (withForeignPtr secKeyFPtr)     skOut <- lift (mallocBytes 32)     lift (memcpy skOut skPtr 32)@@ -553,8 +612,8 @@     keyPairPtr <- ContT (withForeignPtr keyPairFPtr)     tweakPtr <- ContT (withForeignPtr tweakFPtr)     lift $ do-        keyPairOut <- (mallocBytes 96)-        _ <- (memcpy keyPairOut keyPairPtr 96)+        keyPairOut <- mallocBytes 96+        _ <- memcpy keyPairOut keyPairPtr 96         ret <- Prim.keypairXonlyTweakAdd ctx keyPairOut tweakPtr         if isSuccess ret             then Just . KeyPair <$> newForeignPtr finalizerFree keyPairOut@@ -578,62 +637,6 @@                 else free sigBuf $> Nothing  --- | Extra parameters object for alternative nonce generation-data SchnorrExtra a = Storable a =>-    SchnorrExtra-    { schnorrExtraNonceFunHardened :: ByteString -> SecKey -> PubKeyXO -> ByteString -> a -> Maybe (SizedByteArray 32 ByteString)-    , schnorrExtraData :: a-    }----- | Compute a schnorr signature with an alternative scheme for generating nonces, it is not recommended you use this--- unless you know what you are doing. Instead, favor the usage of 'schnorrSign'-schnorrSignCustom :: forall a. KeyPair -> ByteString -> SchnorrExtra a -> Maybe Signature-schnorrSignCustom KeyPair{..} msg SchnorrExtra{..} = unsafePerformIO . evalContT $ do-    (msgPtr, msgLen) <- ContT (unsafeUseByteString msg)-    keyPairPtr <- ContT (withForeignPtr keyPairFPtr)-    lift $ do-        sigBuf <- mallocBytes 64-        -- convert fn into funptr-        funptr <- mkNonceFunHardened primFn-        -- allocate memory for extra data ptr-        dataptr <- malloc-        -- copy data to new pointer-        poke dataptr schnorrExtraData-        -- allocate extraparams structure-        extraPtr <- mallocBytes (4 + sizeOf funptr + sizeOf dataptr)-        -- fill magic-        pokeByteOff extraPtr 0 (0xDA :: Word8)-        pokeByteOff extraPtr 1 (0x6F :: Word8)-        pokeByteOff extraPtr 2 (0xB3 :: Word8)-        pokeByteOff extraPtr 3 (0x8C :: Word8)-        -- fill funptr-        pokeByteOff extraPtr 4 funptr-        -- fill dataptr-        pokeByteOff extraPtr (4 + sizeOf funptr) dataptr-        ret <- Prim.schnorrsigSignCustom ctx sigBuf msgPtr msgLen keyPairPtr extraPtr-        freeHaskellFunPtr funptr-        free dataptr-        free extraPtr-        if isSuccess ret-            then Just . Signature <$> newForeignPtr finalizerFree sigBuf-            else free sigBuf $> Nothing-    where-        primFn :: Storable a => Prim.NonceFunHardened a-        primFn outBuf msgPtr msgLen sk xopk algo algolen dataPtr = do-            msg <- unsafePackByteString (msgPtr, msgLen)-            sk <- SecKey <$> newForeignPtr_ (castPtr sk)-            xopk <- PubKeyXO <$> newForeignPtr_ (castPtr xopk)-            algo <- unsafePackByteString (algo, algolen)-            extra <- peek dataPtr-            case schnorrExtraNonceFunHardened msg sk xopk algo extra of-                Nothing -> pure 0-                Just bs -> evalContT $ do-                    (hashPtr, _) <- ContT (unsafeUseByteString (unSizedByteArray bs))-                    lift (memcpy outBuf hashPtr 32)-                    pure 1-- -- | Verify the authenticity of a schnorr signature. @True@ means the 'Signature' is correct. schnorrVerify :: PubKeyXO -> ByteString -> Signature -> Bool schnorrVerify PubKeyXO{..} bs Signature{..} = unsafePerformIO . evalContT $ do@@ -662,7 +665,7 @@ -- | Combine a list of 'PubKeyXY's into a single 'PubKeyXY'. This will result in @Nothing@ if the group operation results -- in the Point at Infinity pubKeyCombine :: [PubKeyXY] -> Maybe PubKeyXY-pubKeyCombine keys = unsafePerformIO $ do+pubKeyCombine keys@(_ : _) = unsafePerformIO $ do     let n = length keys     keysBuf <- mallocBytes (64 * n)     for_ (zip [0 ..] keys) $ \(i, PubKeyXY{..}) ->@@ -672,6 +675,7 @@     if isSuccess ret         then Just . PubKeyXY <$> newForeignPtr finalizerFree outBuf         else free outBuf $> Nothing+pubKeyCombine [] = Nothing   -- | Negate a 'PubKeyXY'
+ src/Crypto/Secp256k1/Gen.hs view
@@ -0,0 +1,30 @@+module Crypto.Secp256k1.Gen where++import Crypto.Secp256k1 (KeyPair, PubKeyXO, PubKeyXY, SecKey, Tweak, derivePubKey, importSecKey, importTweak, keyPairCreate, xyToXO)+import Hedgehog (MonadGen)+import Hedgehog.Gen (bytes, discard, prune)+import Hedgehog.Range (singleton)+++secKeyGen :: MonadGen m => m SecKey+secKeyGen = do+    bs <- prune $ bytes (singleton 32)+    maybe discard pure (importSecKey bs)+++pubKeyXYGen :: MonadGen m => m PubKeyXY+pubKeyXYGen = derivePubKey <$> secKeyGen+++pubKeyXOGen :: MonadGen m => m PubKeyXO+pubKeyXOGen = fst . xyToXO <$> pubKeyXYGen+++keyPairGen :: MonadGen m => m KeyPair+keyPairGen = keyPairCreate <$> secKeyGen+++tweakGen :: MonadGen m => m Tweak+tweakGen = do+    bs <- prune $ bytes (singleton 32)+    maybe discard pure (importTweak bs)
src/Crypto/Secp256k1/Internal.hs view
@@ -1,6 +1,7 @@ module Crypto.Secp256k1.Internal where  import Crypto.Secp256k1.Prim+import qualified Data.ByteArray.Encoding as BA import Data.ByteString (ByteString) import qualified Data.ByteString as BS import qualified Data.ByteString.Unsafe as BU@@ -34,3 +35,11 @@ isSuccess 0 = False isSuccess 1 = True isSuccess n = error $ "isSuccess expected 0 or 1 but got " ++ show n+++encodeBase16 :: ByteString -> ByteString+encodeBase16 = BA.convertToBase BA.Base16+++decodeBase16 :: ByteString -> Either String ByteString+decodeBase16 = BA.convertFromBase BA.Base16
src/Crypto/Secp256k1/Prim.hs view
@@ -1,8 +1,9 @@+{-# LANGUAGE CApiFFI #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DerivingStrategies #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE RankNTypes #-}+{-# OPTIONS_GHC -Wno-dodgy-foreign-imports #-}  -- | -- Module      : Crypto.Secp256k1.Prim@@ -220,7 +221,7 @@ -- You should call this after 'contextCreate' or -- 'contextClone' (and 'contextPreallocatedCreate' or -- 'contextClone', resp.), and you may call this repeatedly afterwards.-foreign import ccall safe "secp256k1.h secp256k1_context_randomize"+foreign import capi safe "secp256k1.h secp256k1_context_randomize"     contextRandomize ::         -- | __Mutated__: pointer to a context object (cannot be NULL)         Ctx ->@@ -238,7 +239,7 @@ --  This function uses malloc to allocate memory. It is guaranteed that malloc is --  called at most once for every call of this function. If you need to avoid dynamic --  memory allocation entirely, see the functions in the [Preallocated](#g:preallocated) section.-foreign import ccall safe "secp256k1.h secp256k1_context_clone"+foreign import capi safe "secp256k1.h secp256k1_context_clone"     contextClone ::         -- | __Input:__ an existing context to copy (cannot be NULL)         Ctx ->@@ -253,7 +254,7 @@ --  memory allocation entirely, see the functions in secp256k1_preallocated.h. -- --  See also 'contextRandomize'.-foreign import ccall safe "secp256k1.h secp256k1_context_create"+foreign import capi safe "secp256k1.h secp256k1_context_create"     contextCreate ::         -- | __Input:__ which parts of the context to initialize.         ContextFlags ->@@ -270,7 +271,7 @@ --  'contextPreallocatedCreate' or 'contextPreallocatedClone', the --  behaviour is undefined. In that case, 'contextPreallocatedDestroy' must --  be used instead.-foreign import ccall safe "secp256k1.h secp256k1_context_destroy"+foreign import capi safe "secp256k1.h secp256k1_context_destroy"     contextDestroy ::         -- | an existing context to destroy, constructed using 'contextCreate' or 'contextClone'         Ctx ->@@ -301,7 +302,7 @@ --  type serialization/parsing functions which require a context object to maintain --  API consistency, but currently do not require expensive precomputations or dynamic --  allocations.-foreign import ccall safe "secp256k1.h secp256k1_context_no_precomp"+foreign import ccall unsafe "secp256k1.h secp256k1_context_no_precomp"     contextNoPrecomp :: Ctx  @@ -314,7 +315,7 @@ --  The block of memory is exclusively owned by the created context object during --  the lifetime of this context object, see the description of --  'contextPreallocatedCreate' for details.-foreign import ccall safe "secp256k1.h secp256k1_context_preallocated_clone"+foreign import capi safe "secp256k1_preallocated.h secp256k1_context_preallocated_clone"     contextPreallocatedClone ::         -- | __Mutated:__ an existing context to copy (cannot be NULL)         Ctx ->@@ -327,7 +328,7 @@  -- | Determine the memory size of a secp256k1 context object to be copied into --  caller-provided memory.-foreign import ccall safe "secp256k1.h secp256k1_context_preallocated_clone_size"+foreign import capi safe "secp256k1_preallocated.h secp256k1_context_preallocated_clone_size"     contextPreallocatedCloneSize ::         -- | __Input:__ an existing context to copy (cannot be NULL)         Ctx ->@@ -353,7 +354,7 @@ -- --  See also 'contextRandomize' --  and 'contextPreallocatedDestroy'.-foreign import ccall safe "secp256k1.h secp256k1_context_preallocated_create"+foreign import capi safe "secp256k1_preallocated.h secp256k1_context_preallocated_create"     contextPreallocatedCreate ::         -- | __Mutated:__ a pointer to a rewritable contiguous block of memory of         -- size at least 'contextPreallocatedSize' (flags)@@ -380,7 +381,7 @@ --  of memory properly after this function returns, e.g., by calling free on the --  preallocated pointer given to 'contextPreallocatedCreate' or --  'contextPreallocatedClone'.-foreign import ccall safe "secp256k1.h secp256k1_context_preallocated_destroy"+foreign import capi safe "secp256k1_preallocated.h secp256k1_context_preallocated_destroy"     contextPreallocatedDestroy ::         -- | an existing context to destroy, constructed using 'contextPreallocatedCreate' or         -- 'contextPreallocatedClone' (cannot be NULL)@@ -393,7 +394,7 @@ -- --  The purpose of this function is to determine how much memory must be provided --  to 'contextPreallocatedCreate'.-foreign import ccall safe "secp256k1.h secp256k1_context_preallocated_size"+foreign import capi safe "secp256k1_preallocated.h secp256k1_context_preallocated_size"     contextPreallocatedSize ::         -- | __Input:__ which parts of the context to initialize.         CUInt ->@@ -415,7 +416,7 @@ --  crashing. -- --  See also 'contextSetIllegalCallback'.-foreign import ccall safe "secp256k1.h secp256k1_context_set_error_callback"+foreign import capi safe "secp256k1.h secp256k1_context_set_error_callback"     contextSetErrorCallback ::         -- | an existing context object (cannot be NULL)         Ctx ->@@ -461,7 +462,7 @@ --  the data pointer argument set to NULL. -- --  See also 'contextSetErrorCallback'.-foreign import ccall safe "secp256k1.h secp256k1_context_set_illegal_callback"+foreign import capi safe "secp256k1.h secp256k1_context_set_illegal_callback"     contextSetIllegalCallback ::         -- | an existing context object (cannot be NULL)         Ctx ->@@ -477,7 +478,7 @@   -- | Compute an EC Diffie-Hellman secret in constant time-foreign import ccall safe "secp256k1.h secp256k1_ecdh"+foreign import capi safe "secp256k1.h secp256k1_ecdh"     ecdh ::         -- | pointer to a context object (cannot be NULL)         Ctx ->@@ -499,13 +500,13 @@  -- | A default ECDH hash function (currently equal to 'ecdhHashFunctionSha256'). -- Populates the output parameter with 32 bytes.-foreign import ccall safe "secp256k1.h &secp256k1_ecdh_hash_function_default"+foreign import capi safe "secp256k1_ecdh.h value secp256k1_ecdh_hash_function_default"     ecdhHashFunctionDefault :: FunPtr (EcdhHashFun a)   -- | An implementation of SHA256 hash function that applies to compressed public key. -- Populates the output parameter with 32 bytes.-foreign import ccall safe "secp256k1.h &secp256k1_ecdh_hash_function_sha256"+foreign import capi safe "secp256k1_ecdh.h value secp256k1_ecdh_hash_function_sha256"     ecdhHashFunctionSha256 :: FunPtr (EcdhHashFun a)  @@ -513,14 +514,14 @@   -- | A default safe nonce generation function (currently equal to 'nonceFunctionRfc6979').-foreign import ccall safe "secp256k1.h &secp256k1_nonce_function_default"+foreign import capi safe "secp256k1.h value secp256k1_nonce_function_default"     nonceFunctionDefault :: FunPtr (NonceFun a)   -- | An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. -- If a data pointer is passed, it is assumed to be a pointer to 32 bytes of -- extra entropy.-foreign import ccall safe "secp256k1.h &secp256k1_nonce_function_rfc6979"+foreign import capi safe "secp256k1.h value secp256k1_nonce_function_rfc6979"     nonceFunctionRfc6979 :: FunPtr (NonceFun a)  @@ -528,7 +529,7 @@   -- | Recover an ECDSA public key from a signature.-foreign import ccall safe "secp256k1.h secp256k1_ecdsa_recover"+foreign import capi safe "secp256k1_recovery.h secp256k1_ecdsa_recover"     ecdsaRecover ::         -- | pointer to a context object, initialized for verification (cannot be NULL)         Ctx ->@@ -544,7 +545,7 @@   -- | Convert a recoverable signature into a normal signature.-foreign import ccall safe "secp256k1.h secp256k1_ecdsa_recoverable_signature_convert"+foreign import capi safe "secp256k1_recovery.h secp256k1_ecdsa_recoverable_signature_convert"     ecdsaRecoverableSignatureConvert ::         -- | a secp256k1 context object         Ctx ->@@ -557,7 +558,7 @@   -- | Parse a compact ECDSA signature (64 bytes + recovery id).-foreign import ccall safe "secp256k1.h secp256k1_ecdsa_recoverable_signature_parse_compact"+foreign import capi safe "secp256k1_recovery.h secp256k1_ecdsa_recoverable_signature_parse_compact"     ecdsaRecoverableSignatureParseCompact ::         -- | a secp256k1 context object         Ctx ->@@ -572,7 +573,7 @@   -- | Serialize an ECDSA signature in compact format (64 bytes + recovery id).-foreign import ccall safe "secp256k1.h secp256k1_ecdsa_recoverable_signature_serialize_compact"+foreign import capi safe "secp256k1_recovery.h secp256k1_ecdsa_recoverable_signature_serialize_compact"     ecdsaRecoverableSignatureSerializeCompact ::         -- | a secp256k1 context object         Ctx ->@@ -587,7 +588,7 @@   -- | Create a recoverable ECDSA signature.-foreign import ccall safe "secp256k1.h secp256k1_ecdsa_sign_recoverable"+foreign import capi safe "secp256k1_recovery.h secp256k1_ecdsa_sign_recoverable"     ecdsaSignRecoverable ::         -- | pointer to a context object, initialized for signing (cannot be NULL)         Ctx ->@@ -613,7 +614,7 @@ -- -- The created signature is always in lower-S form. See -- 'ecdsaSignatureNormalize' for more details.-foreign import ccall safe "secp256k1.h secp256k1_ecdsa_sign"+foreign import capi safe "secp256k1.h secp256k1_ecdsa_sign"     ecdsaSign ::         -- | pointer to a context object, initialized for signing (cannot be NULL)         Ctx ->@@ -642,7 +643,7 @@ -- validation, but be aware that doing so results in malleable signatures. -- -- For details, see the comments for that function.-foreign import ccall safe "secp256k1.h secp256k1_ecdsa_verify"+foreign import capi safe "secp256k1.h secp256k1_ecdsa_verify"     ecdsaVerify ::         -- | a secp256k1 context object, initialized for verification.         Ctx ->@@ -695,7 +696,7 @@ --  lower-S form, and 'ecdsaVerify' will not accept others. In case --  signatures come from a system that cannot enforce this property, --  'ecdsaSignatureNormalize' must be called before verification.-foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_normalize"+foreign import capi safe "secp256k1.h secp256k1_ecdsa_signature_normalize"     ecdsaSignatureNormalize ::         -- | a secp256k1 context object         Ctx ->@@ -723,7 +724,7 @@ --  After the call, sig will always be initialized. If parsing failed or R or --  S are zero, the resulting sig value is guaranteed to fail validation for any --  message and public key.-foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_parse_compact"+foreign import capi safe "secp256k1.h secp256k1_ecdsa_signature_parse_compact"     ecdsaSignatureParseCompact ::         -- | __Input:__ a secp256k1 context object         Ctx ->@@ -743,7 +744,7 @@ --  After the call, sig will always be initialized. If parsing failed or the --  encoded numbers are out of range, signature validation with it is --  guaranteed to fail for every message and public key.-foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_parse_der"+foreign import capi safe "secp256k1.h secp256k1_ecdsa_signature_parse_der"     ecdsaSignatureParseDer ::         -- | __Input:__ a secp256k1 context object         Ctx ->@@ -760,7 +761,7 @@ -- | Serialize an ECDSA signature in compact (64 byte) format. -- --  See 'ecdsaSignatureParseCompact' for details about the encoding.-foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_serialize_compact"+foreign import capi safe "secp256k1.h secp256k1_ecdsa_signature_serialize_compact"     ecdsaSignatureSerializeCompact ::         -- | __Input:__ a secp256k1 context object         Ctx ->@@ -773,7 +774,7 @@   -- | Serialize an ECDSA signature in DER format.-foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_serialize_der"+foreign import capi safe "secp256k1.h secp256k1_ecdsa_signature_serialize_der"     ecdsaSignatureSerializeDer ::         -- | __Input:__ a secp256k1 context object         Ctx ->@@ -794,7 +795,7 @@   -- | Compare two public keys using lexicographic (of compressed serialization) order-foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_cmp"+foreign import capi safe "secp256k1.h secp256k1_ec_pubkey_cmp"     ecPubkeyCmp ::         -- | __Input:__ a secp256k1 context object.         Ctx ->@@ -825,7 +826,7 @@   -- | Compute the public key for a secret key.-foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_create"+foreign import capi safe "secp256k1.h secp256k1_ec_pubkey_create"     ecPubkeyCreate ::         -- | pointer to a context object, initialized for signing (cannot be NULL)         Ctx ->@@ -839,7 +840,7 @@   -- | Negates a public key in place.-foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_negate"+foreign import capi safe "secp256k1.h secp256k1_ec_pubkey_negate"     ecPubkeyNegate ::         -- | pointer to a context object         Ctx ->@@ -854,7 +855,7 @@ --  This function supports parsing compressed (33 bytes, header byte 0x02 or --  0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header --  byte 0x06 or 0x07) format public keys.-foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_parse"+foreign import capi safe "secp256k1.h secp256k1_ec_pubkey_parse"     ecPubkeyParse ::         -- | a secp256k1 context object.         Ctx ->@@ -871,7 +872,7 @@   -- | Serialize a pubkey object into a serialized byte sequence.-foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_serialize"+foreign import capi safe "secp256k1.h secp256k1_ec_pubkey_serialize"     ecPubkeySerialize ::         -- | a secp256k1 context object.         Ctx ->@@ -892,7 +893,7 @@   -- | Tweak a public key by adding tweak times the generator to it.-foreign import ccall unsafe "secp256k1.h secp256k1_ec_pubkey_tweak_add"+foreign import capi unsafe "secp256k1.h secp256k1_ec_pubkey_tweak_add"     ecPubkeyTweakAdd ::         -- | pointer to a context object initialized for validation (cannot be NULL).         Ctx ->@@ -911,7 +912,7 @@   -- | Tweak a public key by multiplying it by a tweak value.-foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_tweak_mul"+foreign import capi safe "secp256k1.h secp256k1_ec_pubkey_tweak_mul"     ecPubkeyTweakMul ::         -- | pointer to a context object initialized for validation (cannot be NULL).         Ctx ->@@ -928,7 +929,7 @@   -- | Negates a secret key in place.-foreign import ccall safe "secp256k1.h secp256k1_ec_seckey_negate"+foreign import capi safe "secp256k1.h secp256k1_ec_seckey_negate"     ecSeckeyNegate ::         -- | pointer to a context object         Ctx ->@@ -944,7 +945,7 @@   -- | Tweak a secret key by adding tweak to it.-foreign import ccall safe "secp256k1.h secp256k1_ec_seckey_tweak_add"+foreign import capi safe "secp256k1.h secp256k1_ec_seckey_tweak_add"     ecSeckeyTweakAdd ::         -- | pointer to a context object (cannot be NULL).         Ctx ->@@ -965,7 +966,7 @@   -- | Tweak a secret key by multiplying it by a tweak.-foreign import ccall safe "secp256k1.h secp256k1_ec_seckey_tweak_mul"+foreign import capi safe "secp256k1.h secp256k1_ec_seckey_tweak_mul"     ecSeckeyTweakMul ::         -- | pointer to a context object (cannot be NULL).         Ctx ->@@ -989,7 +990,7 @@ --  when interpreted as an integer (most significant byte first). The --  probability of choosing a 32-byte string uniformly at random which is an --  invalid secret key is negligible.-foreign import ccall safe "secp256k1.h secp256k1_ec_seckey_verify"+foreign import capi safe "secp256k1.h secp256k1_ec_seckey_verify"     ecSecKeyVerify ::         -- | pointer to a context object (cannot be NULL)         Ctx ->@@ -1000,7 +1001,7 @@   -- | Compute the keypair for a secret key.-foreign import ccall safe "secp256k1.h secp256k1_keypair_create"+foreign import capi safe "secp256k1_extrakeys.h secp256k1_keypair_create"     keypairCreate ::         -- | pointer to a context object, initialized for signing (cannot be NULL)         Ctx ->@@ -1014,7 +1015,7 @@   -- | Get the public key from a keypair.-foreign import ccall safe "secp256k1.h secp256k1_keypair_pub"+foreign import capi safe "secp256k1_extrakeys.h secp256k1_keypair_pub"     keypairPub ::         -- | pointer to a context object (cannot be NULL)         Ctx ->@@ -1029,7 +1030,7 @@   -- | Get the secret key from a keypair.-foreign import ccall safe "secp256k1.h secp256k1_keypair_sec"+foreign import capi safe "secp256k1_extrakeys.h secp256k1_keypair_sec"     keypairSec ::         -- | pointer to a context object (cannot be NULL)         Ctx ->@@ -1045,7 +1046,7 @@ -- --  This is the same as calling 'keypairPub' and then --  'xonlyPubkeyFromPubkey'.-foreign import ccall safe "secp256k1.h secp256k1_keypair_xonly_pub"+foreign import capi safe "secp256k1_extrakeys.h secp256k1_keypair_xonly_pub"     keypairXonlyPub ::         -- | pointer to a context object (cannot be NULL)         Ctx ->@@ -1069,7 +1070,7 @@ --  Calling this function and then 'keypairPub' results in the same --  public key as calling 'keypairXonlyPub' and then --  'xonlyPubkeyTweakAdd'.-foreign import ccall safe "secp256k1.h secp256k1_keypair_xonly_tweak_add"+foreign import capi safe "secp256k1_extrakeys.h secp256k1_keypair_xonly_tweak_add"     keypairXonlyTweakAdd ::         -- | pointer to a context object initialized for verification         -- (cannot be NULL)@@ -1100,7 +1101,7 @@ --  function will fail and return 0. The hash will be tagged with algo. --  Therefore, to create BIP-340 compliant signatures, algo must be set to --  "BIP0340/nonce" and algolen to 13.-foreign import ccall safe "secp256k1.h &secp256k1_nonce_function_bip340"+foreign import capi safe "secp256k1_schnorrsig.h value secp256k1_nonce_function_bip340"     nonceFunctionBip340 :: FunPtr (NonceFunHardened a)  @@ -1116,7 +1117,7 @@ --  'taggedSha256' and then sign the hash. Tagged hashing allows --  providing an context-specific tag for domain separation. This prevents --  signatures from being valid in multiple contexts by accident.-foreign import ccall safe "secp256k1.h secp256k1_schnorrsig_sign"+foreign import capi safe "secp256k1_schnorrsig.h secp256k1_schnorrsig_sign"     schnorrsigSign ::         -- | pointer to a context object, initialized for signing (cannot be NULL)         Ctx ->@@ -1143,7 +1144,7 @@ -- --  Creates the same signatures as schnorrsig_sign if msglen is 32 and the --  extraparams.ndata is the same as aux_rand32.-foreign import ccall safe "secp256k1.h secp256k1_schnorrsig_sign_custom"+foreign import capi unsafe "secp256k1_schnorrsig.h secp256k1_schnorrsig_sign_custom"     schnorrsigSignCustom ::         -- | pointer to a context object, initialized for signing (cannot be NULL)         Ctx ->@@ -1162,7 +1163,7 @@   -- | Verify a Schnorr signature.-foreign import ccall safe "secp256k1.h secp256k1_schnorrsig_verify"+foreign import capi safe "secp256k1_schnorrsig.h secp256k1_schnorrsig_verify"     schnorrsigSignVerify ::         -- | a secp256k1 context object, initialized for verification.         Ctx ->@@ -1185,7 +1186,7 @@ --  SHA256(SHA256(tag)||SHA256(tag)||msg). Therefore, tagged hash --  implementations optimized for a specific tag can precompute the SHA256 state --  after hashing the tag hashes.-foreign import ccall safe "secp256k1.h secp256k1_tagged_sha256"+foreign import capi safe "secp256k1_schnorrsig.h secp256k1_tagged_sha256"     taggedSha256 ::         -- | pointer to a context object         Ctx ->@@ -1207,7 +1208,7 @@   -- | Compare two x-only public keys using lexicographic order-foreign import ccall safe "secp256k1.h secp256k1_xonly_pubkey_cmp"+foreign import capi safe "secp256k1_schnorrsig.h secp256k1_xonly_pubkey_cmp"     xonlyPubkeyCmp ::         -- | a secp256k1 context object.         Ctx ->@@ -1222,7 +1223,7 @@   -- | Converts a 'Pubkey64' into a 'XonlyPubkey64'.-foreign import ccall safe "secp256k1.h secp256k1_xonly_pubkey_from_pubkey"+foreign import capi safe "secp256k1_schnorrsig.h secp256k1_xonly_pubkey_from_pubkey"     xonlyPubkeyFromPubkey ::         -- | pointer to a context object (cannot be NULL)         Ctx ->@@ -1241,7 +1242,7 @@   -- | Parse a 32-byte sequence into a 'XonlyPubkey64' object.-foreign import ccall safe "secp256k1.h secp256k1_xonly_pubkey_parse"+foreign import capi safe "secp256k1_schnorrsig.h secp256k1_xonly_pubkey_parse"     xonlyPubkeyParse ::         -- | a secp256k1 context object (cannot be NULL).         Ctx ->@@ -1257,7 +1258,7 @@   -- | Serialize an 'XonlyPubkey64' object into a 32-byte sequence.-foreign import ccall safe "secp256k1.h secp256k1_xonly_pubkey_serialize"+foreign import capi safe "secp256k1_schnorrsig.h secp256k1_xonly_pubkey_serialize"     xonlyPubkeySerialize ::         -- | a secp256k1 context object (cannot be NULL).         Ctx ->@@ -1277,7 +1278,7 @@ --  Note that the resulting point can not in general be represented by an x-only --  pubkey because it may have an odd Y coordinate. Instead, the output_pubkey --  is a normal 'Pubkey64'.-foreign import ccall safe "secp256k1.h secp256k1_xonly_pubkey_tweak_add"+foreign import capi safe "secp256k1_schnorrsig.h secp256k1_xonly_pubkey_tweak_add"     xonlyPubkeyTweakAdd ::         -- | pointer to a context object initialized for verification         -- (cannot be NULL)@@ -1311,7 +1312,7 @@ --  Note that this alone does _not_ verify that the tweaked pubkey is a --  commitment. If the tweak is not chosen in a specific way, the tweaked pubkey --  can easily be the result of a different internal_pubkey and tweak.-foreign import ccall safe "secp256k1.h secp256k1_xonly_pubkey_tweak_add_check"+foreign import capi safe "secp256k1_schnorrsig.h secp256k1_xonly_pubkey_tweak_add_check"     xonlyPubkeyTweakAddCheck ::         -- | pointer to a context object initialized for verification         -- (cannot be NULL)@@ -1338,7 +1339,7 @@   -- | Create a secp256k1 scratch space object.-foreign import ccall safe "secp256k1.h secp256k1_scratch_space_create"+foreign import capi safe "secp256k1.h secp256k1_scratch_space_create"     scratchSpaceCreate ::         -- | an existing context object (cannot be NULL)         Ctx ->@@ -1352,7 +1353,7 @@ -- | Destroy a secp256k1 scratch space. -- --  The pointer may not be used afterwards.-foreign import ccall safe "secp256k1.h secp256k1_scratch_space_destroy"+foreign import capi safe "secp256k1.h secp256k1_scratch_space_destroy"     scratchSpaceDestroy ::         -- | a secp256k1 context object.         Ctx ->@@ -1363,7 +1364,7 @@  -- * Deprecated {-# DEPRECATED ecPrivkeyNegate "use ecSeckeyNegate instead" #-}-foreign import ccall safe "secp256k1.h secp256k1_ec_privkey_negate"+foreign import capi safe "secp256k1.h secp256k1_ec_privkey_negate"     ecPrivkeyNegate ::         Ctx ->         Ptr Tweak32 ->@@ -1371,7 +1372,7 @@   {-# DEPRECATED ecPrivkeyTweakAdd "use ecSeckeyTweakAdd instead" #-}-foreign import ccall safe "secp256k1.h secp256k1_ec_privkey_tweak_add"+foreign import capi safe "secp256k1.h secp256k1_ec_privkey_tweak_add"     ecPrivkeyTweakAdd ::         Ctx ->         Ptr Seckey32 ->@@ -1380,7 +1381,7 @@   {-# DEPRECATED ecPrivkeyTweakMul "use ecSeckeyTweakMul instead" #-}-foreign import ccall safe "secp256k1.h secp256k1_ec_privkey_tweak_mul"+foreign import capi safe "secp256k1.h secp256k1_ec_privkey_tweak_mul"     ecPrivkeyTweakMul ::         Ctx ->         Ptr Seckey32 ->
test/Crypto/Secp256k1/PrimSpec.hs view
@@ -3,15 +3,15 @@ module Crypto.Secp256k1.PrimSpec (spec) where  import Control.Monad-import Control.Monad.Trans+ import Crypto.Secp256k1.Internal+import qualified Data.ByteArray.Encoding as BA import Data.ByteString (     ByteString,     copy,     packCStringLen,     useAsCStringLen,  )-import qualified Data.ByteString.Base16 as B16 import Data.Either (fromRight) import Foreign import System.Entropy@@ -21,446 +21,426 @@  spec :: Spec spec = do-    describe "housekeeping" $ do-        it "creates context" createContextTest-        it "randomizes context" randomizeContextTest-        it "clones context" cloneContextTest-    describe "serialization" $ do-        it "parses public key" ecPubkeyParseTest-        it "serializes public key" ecPubKeySerializeTest-        it "parses DER signature" ecdsaSignatureParseDerTest-        it "serializes DER signature" ecdsaSignatureSerializeDerTest-    describe "signatures" $ do-        it "verifies signature" ecdsaVerifyTest-        it "signs message" ecdsaSignTest-    describe "secret keys" $ do-        it "verifies secret key" ecSecKeyVerifyTest-        it "creates public key" ecPubkeyCreateTest-        it "adds secret key" ecSecKeyTweakAddTest-        it "multiplies secret key" ecSecKeyTweakMulTest-    describe "public keys" $ do-        it "adds public key" ecPubKeyTweakAddTest-        it "multiplies public key" ecPubKeyTweakMulTest-        it "combines public keys" ecPubKeyCombineTest---withEntropy :: (Ptr Seed32 -> IO a) -> IO a-withEntropy f =-    getEntropy 32 >>= \e ->-        useByteString e $ \(s, _) -> f s---createContextTest :: Assertion-createContextTest = do-    context_ptr <- liftIO $ contextCreate signVerify-    assertBool "context not null" $ context_ptr /= nullPtr---randomizeContextTest :: Assertion-randomizeContextTest = do-    ret <--        liftIO $-            contextCreate sign >>= \x ->-                withEntropy (contextRandomize x)-    assertBool "context randomized" $ isSuccess ret---cloneContextTest :: Assertion-cloneContextTest = do-    (x1, x2) <- liftIO $ do-        x1 <- contextCreate signVerify-        ret <- withEntropy $ contextRandomize x1-        unless (isSuccess ret) $ error "failed to randomize context"-        x2 <- contextClone x1-        return (x1, x2)-    assertBool "original context not null" $ x1 /= nullPtr-    assertBool "cloned context not null" $ x2 /= nullPtr-    assertBool "context ptrs different" $ x1 /= x2---ecPubkeyParseTest :: Assertion-ecPubkeyParseTest = do-    ret <- liftIO $-        useAsCStringLen der $ \(i, il) -> do-            x <- contextCreate verify-            allocaBytes 64 $ \pubkey ->-                ecPubKeyParse x pubkey (castPtr i) (fromIntegral il)-    assertBool "parsed public key" (isSuccess ret)-    where-        der =-            fromRight undefined $-                B16.decodeBase16-                    "03dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd44705"---ecPubKeySerializeTest :: Assertion-ecPubKeySerializeTest = do-    (ret, dec) <- liftIO $-        useByteString der $ \(i, il) ->-            allocaBytes 64 $ \k ->-                alloca $ \ol ->-                    allocaBytes 72 $ \o -> do-                        poke ol 72-                        x <- contextCreate verify-                        ret1 <- ecPubKeyParse x k i il-                        unless (isSuccess ret1) $ error "failed to parse pubkey"-                        ret2 <- ecPubKeySerialize x o ol k compressed-                        len <- fromIntegral <$> peek ol-                        decoded <- packCStringLen (castPtr o, len)-                        return (ret2, decoded)-    assertBool "serialized public key successfully" $ isSuccess ret-    assertEqual "public key matches" der dec-    where-        der =-            fromRight undefined $-                B16.decodeBase16-                    "03dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd44705"---ecdsaSignatureParseDerTest :: Assertion-ecdsaSignatureParseDerTest = do-    ret <- liftIO $-        useAsCStringLen der $ \(d, dl) -> allocaBytes 64 $ \s -> do-            x <- contextCreate verify-            ecdsaSignatureParseDer x s (castPtr d) (fromIntegral dl)-    assertBool "parsed signature successfully" $ isSuccess ret-    where-        der =-            fromRight undefined $-                B16.decodeBase16-                    "3045022100f502bfa07af43e7ef265618b0d929a7619ee01d6150e37eb6eaaf2c8bd37\-                    \fb2202206f0415ab0e9a977afd78b2c26ef39b3952096d319fd4b101c768ad6c132e30\-                    \45"---parseDer :: Ctx -> ByteString -> IO ByteString-parseDer x bs =-    useAsCStringLen bs $ \(d, dl) ->-        allocaBytes 64 $ \s -> do-            ret <- ecdsaSignatureParseDer x s (castPtr d) (fromIntegral dl)-            unless (isSuccess ret) $ error "could not parse DER"-            packByteString (s, 64)---ecdsaSignatureSerializeDerTest :: Assertion-ecdsaSignatureSerializeDerTest = do-    (ret, enc) <- liftIO $ do-        x <- contextCreate verify-        sig <- parseDer x der-        alloca $ \ol ->-            allocaBytes 72 $ \o ->-                useByteString sig $ \(s, _) -> do-                    poke ol 72-                    ret <- ecdsaSignatureSerializeDer x o ol s-                    len <- fromIntegral <$> peek ol-                    enc <- packCStringLen (castPtr o, len)-                    return (ret, enc)-    assertBool "serialization successful" $ isSuccess ret-    assertEqual "signatures match" der enc-    where-        der =-            fromRight undefined $-                B16.decodeBase16-                    "3045022100f502bfa07af43e7ef265618b0d929a7619ee01d6150e37eb6eaaf2c8bd37\-                    \fb2202206f0415ab0e9a977afd78b2c26ef39b3952096d319fd4b101c768ad6c132e30\-                    \45"---ecdsaVerifyTest :: Assertion-ecdsaVerifyTest = do-    ret <- liftIO $ do-        x <- contextCreate verify-        sig <- parseDer x der-        pk <- useByteString pub $ \(p, pl) ->-            allocaBytes 64 $ \k -> do-                ret <- ecPubKeyParse x k p (fromIntegral pl)-                unless (isSuccess ret) $ error "could not parse public key"-                packByteString (k, 64)-        useByteString msg $ \(m, _) ->-            useByteString pk $ \(k, _) ->-                useByteString sig $ \(s, _) ->-                    ecdsaVerify x s m k-    assertBool "signature valid" $ isSuccess ret-    where-        der =-            fromRight undefined $-                B16.decodeBase16-                    "3045022100f502bfa07af43e7ef265618b0d929a7619ee01d6150e37eb6eaaf2c8bd37\-                    \fb2202206f0415ab0e9a977afd78b2c26ef39b3952096d319fd4b101c768ad6c132e30\-                    \45"-        pub =-            fromRight undefined $-                B16.decodeBase16-                    "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd447051221\-                    \3d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"-        msg =-            fromRight undefined $-                B16.decodeBase16-                    "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"-+    pure () -signCtx :: IO Ctx-signCtx =-    contextCreate sign >>= \c ->-        withEntropy (contextRandomize c) >>= \r ->-            unless (isSuccess r) (error "failed to randomize context") >> return c+--     describe "housekeeping" $ do+--         it "creates context" createContextTest+--         it "randomizes context" randomizeContextTest+--         it "clones context" cloneContextTest+--     describe "serialization" $ do+--         it "parses public key" ecPubkeyParseTest+--         it "serializes public key" ecPubKeySerializeTest+--         it "parses DER signature" ecdsaSignatureParseDerTest+--         it "serializes DER signature" ecdsaSignatureSerializeDerTest+--     describe "signatures" $ do+--         it "verifies signature" ecdsaVerifyTest+--         it "signs message" ecdsaSignTest+--     describe "secret keys" $ do+--         it "verifies secret key" ecSecKeyVerifyTest+--         it "creates public key" ecPubkeyCreateTest+--         it "adds secret key" ecSecKeyTweakAddTest+--         it "multiplies secret key" ecSecKeyTweakMulTest+--     describe "public keys" $ do+--         it "adds public key" ecPubKeyTweakAddTest+--         it "multiplies public key" ecPubKeyTweakMulTest+--         it "combines public keys" ecPubKeyCombineTest +-- withEntropy :: (Ptr Seed32 -> IO a) -> IO a+-- withEntropy f =+--     getEntropy 32 >>= \e ->+--         useByteString e $ \(s, _) -> f s -createPubKey :: Ctx -> Ptr SecKey32 -> Ptr PubKey64 -> IO ()-createPubKey x k p = do-    ret <- ecPubKeyCreate x p k-    unless (isSuccess ret) $ error "failed to create public key"+-- createContextTest :: Assertion+-- createContextTest = do+--     context_ptr <- liftIO $ contextCreate signVerify+--     assertBool "context not null" $ context_ptr /= nullPtr +-- randomizeContextTest :: Assertion+-- randomizeContextTest = do+--     ret <-+--         liftIO $+--             contextCreate sign >>= \x ->+--                 withEntropy (contextRandomize x)+--     assertBool "context randomized" $ isSuccess ret -ecdsaSignTest :: Assertion-ecdsaSignTest = do-    der <- liftIO $ do-        x <- signCtx-        allocaBytes 64 $ \s ->-            useByteString msg $ \(m, _) ->-                useByteString key $ \(k, _) ->-                    alloca $ \ol ->-                        allocaBytes 72 $ \o -> do-                            poke ol 72-                            ret1 <- ecdsaSign x s m k nullFunPtr nullPtr-                            unless (isSuccess ret1) $ error "could not sign message"-                            ret2 <- ecdsaSignatureSerializeDer x o ol s-                            unless (isSuccess ret2) $ error "could not serialize signature"-                            len <- peek ol-                            packCStringLen (castPtr o, fromIntegral len)-    ret <- liftIO $ do-        pub <- allocaBytes 64 $ \p ->-            useByteString key $ \(s, _) -> do-                x <- signCtx-                createPubKey x s p-                packByteString (p, 64)-        useByteString msg $ \(m, _) ->-            useByteString pub $ \(p, _) -> do-                x <- contextCreate verify-                s' <- parseDer x der-                useByteString s' $ \(s, _) -> ecdsaVerify x s m p-    assertBool "signature matches" (isSuccess ret)-    where-        msg =-            fromRight undefined $-                B16.decodeBase16-                    "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"-        key =-            fromRight undefined $-                B16.decodeBase16-                    "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"+-- cloneContextTest :: Assertion+-- cloneContextTest = do+--     (x1, x2) <- liftIO $ do+--         x1 <- contextCreate signVerify+--         ret <- withEntropy $ contextRandomize x1+--         unless (isSuccess ret) $ error "failed to randomize context"+--         x2 <- contextClone x1+--         return (x1, x2)+--     assertBool "original context not null" $ x1 /= nullPtr+--     assertBool "cloned context not null" $ x2 /= nullPtr+--     assertBool "context ptrs different" $ x1 /= x2 +-- ecPubkeyParseTest :: Assertion+-- ecPubkeyParseTest = do+--     ret <- liftIO $+--         useAsCStringLen der $ \(i, il) -> do+--             x <- contextCreate verify+--             allocaBytes 64 $ \pubkey ->+--                 ecPubKeyParse x pubkey (castPtr i) (fromIntegral il)+--     assertBool "parsed public key" (isSuccess ret)+--     where+--         der =+--             fromRight undefined $+--                 decodeBase16+--                     "03dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd44705" -ecSecKeyVerifyTest :: Assertion-ecSecKeyVerifyTest = do-    ret <- liftIO $-        useByteString key $ \(k, _) -> do-            x <- signCtx-            ecSecKeyVerify x k-    assertBool "valid secret key" $ isSuccess ret-    where-        key =-            fromRight undefined $-                B16.decodeBase16-                    "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"+-- ecPubKeySerializeTest :: Assertion+-- ecPubKeySerializeTest = do+--     (ret, dec) <- liftIO $+--         useByteString der $ \(i, il) ->+--             allocaBytes 64 $ \k ->+--                 alloca $ \ol ->+--                     allocaBytes 72 $ \o -> do+--                         poke ol 72+--                         x <- contextCreate verify+--                         ret1 <- ecPubKeyParse x k i il+--                         unless (isSuccess ret1) $ error "failed to parse pubkey"+--                         ret2 <- ecPubKeySerialize x o ol k compressed+--                         len <- fromIntegral <$> peek ol+--                         decoded <- packCStringLen (castPtr o, len)+--                         return (ret2, decoded)+--     assertBool "serialized public key successfully" $ isSuccess ret+--     assertEqual "public key matches" der dec+--     where+--         der =+--             fromRight undefined $+--                 decodeBase16+--                     "03dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd44705" +-- ecdsaSignatureParseDerTest :: Assertion+-- ecdsaSignatureParseDerTest = do+--     ret <- liftIO $+--         useAsCStringLen der $ \(d, dl) -> allocaBytes 64 $ \s -> do+--             x <- contextCreate verify+--             ecdsaSignatureParseDer x s (castPtr d) (fromIntegral dl)+--     assertBool "parsed signature successfully" $ isSuccess ret+--     where+--         der =+--             fromRight undefined $+--                 decodeBase16+--                     "3045022100f502bfa07af43e7ef265618b0d929a7619ee01d6150e37eb6eaaf2c8bd37\+--                     \fb2202206f0415ab0e9a977afd78b2c26ef39b3952096d319fd4b101c768ad6c132e30\+--                     \45" -ecPubkeyCreateTest :: Assertion-ecPubkeyCreateTest = do-    pk <- liftIO $-        useByteString key $ \(s, _) ->-            allocaBytes 64 $ \k -> do-                x <- signCtx-                createPubKey x s k-                allocaBytes 65 $ \o ->-                    alloca $ \ol -> do-                        poke ol 65-                        rets <- ecPubKeySerialize x o ol k uncompressed-                        unless (isSuccess rets) $ error "failed to serialize public key"-                        len <- fromIntegral <$> peek ol-                        packCStringLen (castPtr o, len)-    assertEqual "public key matches" pub pk-    where-        key =-            fromRight undefined $-                B16.decodeBase16-                    "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"-        pub =-            fromRight undefined $-                B16.decodeBase16-                    "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd447051221\-                    \3d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"+-- parseDer :: Ctx -> ByteString -> IO ByteString+-- parseDer x bs =+--     useAsCStringLen bs $ \(d, dl) ->+--         allocaBytes 64 $ \s -> do+--             ret <- ecdsaSignatureParseDer x s (castPtr d) (fromIntegral dl)+--             unless (isSuccess ret) $ error "could not parse DER"+--             packByteString (s, 64) +-- ecdsaSignatureSerializeDerTest :: Assertion+-- ecdsaSignatureSerializeDerTest = do+--     (ret, enc) <- liftIO $ do+--         x <- contextCreate verify+--         sig <- parseDer x der+--         alloca $ \ol ->+--             allocaBytes 72 $ \o ->+--                 useByteString sig $ \(s, _) -> do+--                     poke ol 72+--                     ret <- ecdsaSignatureSerializeDer x o ol s+--                     len <- fromIntegral <$> peek ol+--                     enc <- packCStringLen (castPtr o, len)+--                     return (ret, enc)+--     assertBool "serialization successful" $ isSuccess ret+--     assertEqual "signatures match" der enc+--     where+--         der =+--             fromRight undefined $+--                 decodeBase16+--                     "3045022100f502bfa07af43e7ef265618b0d929a7619ee01d6150e37eb6eaaf2c8bd37\+--                     \fb2202206f0415ab0e9a977afd78b2c26ef39b3952096d319fd4b101c768ad6c132e30\+--                     \45" -ecSecKeyTweakAddTest :: Assertion-ecSecKeyTweakAddTest = do-    (ret, tweaked) <--        liftIO $-            signCtx >>= \x ->-                useByteString tweak $ \(w, _) ->-                    useByteString key $ \(k, _) -> do-                        ret <- ecSecKeyTweakAdd x k w-                        tweaked <- packByteString (k, 32)-                        return (ret, tweaked)-    assertBool "successful secret key tweak" $ isSuccess ret-    assertEqual "tweaked keys match" expected tweaked-    where-        key =-            fromRight undefined $-                B16.decodeBase16-                    "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"-        tweak =-            fromRight undefined $-                B16.decodeBase16-                    "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"-        expected =-            fromRight undefined $-                B16.decodeBase16-                    "ec1e3ce1cefa18a671d51125e2b249688d934b0e28f5d1665384d9b02f929059"+-- ecdsaVerifyTest :: Assertion+-- ecdsaVerifyTest = do+--     ret <- liftIO $ do+--         x <- contextCreate verify+--         sig <- parseDer x der+--         pk <- useByteString pub $ \(p, pl) ->+--             allocaBytes 64 $ \k -> do+--                 ret <- ecPubKeyParse x k p (fromIntegral pl)+--                 unless (isSuccess ret) $ error "could not parse public key"+--                 packByteString (k, 64)+--         useByteString msg $ \(m, _) ->+--             useByteString pk $ \(k, _) ->+--                 useByteString sig $ \(s, _) ->+--                     ecdsaVerify x s m k+--     assertBool "signature valid" $ isSuccess ret+--     where+--         der =+--             fromRight undefined $+--                 decodeBase16+--                     "3045022100f502bfa07af43e7ef265618b0d929a7619ee01d6150e37eb6eaaf2c8bd37\+--                     \fb2202206f0415ab0e9a977afd78b2c26ef39b3952096d319fd4b101c768ad6c132e30\+--                     \45"+--         pub =+--             fromRight undefined $+--                 decodeBase16+--                     "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd447051221\+--                     \3d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"+--         msg =+--             fromRight undefined $+--                 decodeBase16+--                     "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00" +-- signCtx :: IO Ctx+-- signCtx =+--     contextCreate sign >>= \c ->+--         withEntropy (contextRandomize c) >>= \r ->+--             unless (isSuccess r) (error "failed to randomize context") >> return c -ecSecKeyTweakMulTest :: Assertion-ecSecKeyTweakMulTest = do-    (ret, tweaked) <- liftIO $ do-        x <- contextCreate sign-        retr <- withEntropy $ contextRandomize x-        unless (isSuccess retr) $ error "failed to randomize context"-        useByteString tweak $ \(w, _) -> useByteString key $ \(k, _) -> do-            ret <- ecSecKeyTweakMul x k w-            tweaked <- packByteString (k, 32)-            return (ret, tweaked)-    assertBool "successful secret key tweak" $ isSuccess ret-    assertEqual "tweaked keys match" expected tweaked-    where-        key =-            fromRight undefined $-                B16.decodeBase16-                    "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"-        tweak =-            fromRight undefined $-                B16.decodeBase16-                    "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"-        expected =-            fromRight undefined $-                B16.decodeBase16-                    "a96f5962493acb179f60a86a9785fc7a30e0c39b64c09d24fe064d9aef15e4c0"+-- createPubKey :: Ctx -> Ptr SecKey32 -> Ptr PubKey64 -> IO ()+-- createPubKey x k p = do+--     ret <- ecPubKeyCreate x p k+--     unless (isSuccess ret) $ error "failed to create public key" +-- ecdsaSignTest :: Assertion+-- ecdsaSignTest = do+--     der <- liftIO $ do+--         x <- signCtx+--         allocaBytes 64 $ \s ->+--             useByteString msg $ \(m, _) ->+--                 useByteString key $ \(k, _) ->+--                     alloca $ \ol ->+--                         allocaBytes 72 $ \o -> do+--                             poke ol 72+--                             ret1 <- ecdsaSign x s m k nullFunPtr nullPtr+--                             unless (isSuccess ret1) $ error "could not sign message"+--                             ret2 <- ecdsaSignatureSerializeDer x o ol s+--                             unless (isSuccess ret2) $ error "could not serialize signature"+--                             len <- peek ol+--                             packCStringLen (castPtr o, fromIntegral len)+--     ret <- liftIO $ do+--         pub <- allocaBytes 64 $ \p ->+--             useByteString key $ \(s, _) -> do+--                 x <- signCtx+--                 createPubKey x s p+--                 packByteString (p, 64)+--         useByteString msg $ \(m, _) ->+--             useByteString pub $ \(p, _) -> do+--                 x <- contextCreate verify+--                 s' <- parseDer x der+--                 useByteString s' $ \(s, _) -> ecdsaVerify x s m p+--     assertBool "signature matches" (isSuccess ret)+--     where+--         msg =+--             fromRight undefined $+--                 decodeBase16+--                     "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"+--         key =+--             fromRight undefined $+--                 decodeBase16+--                     "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a" -serializeKey :: Ctx -> Ptr PubKey64 -> IO ByteString-serializeKey x p = allocaBytes 72 $ \d -> alloca $ \dl -> do-    poke dl 72-    ret <- ecPubKeySerialize x d dl p uncompressed-    unless (isSuccess ret) $ error "could not serialize public key"-    len <- peek dl-    packCStringLen (castPtr d, fromIntegral len)+-- ecSecKeyVerifyTest :: Assertion+-- ecSecKeyVerifyTest = do+--     ret <- liftIO $+--         useByteString key $ \(k, _) -> do+--             x <- signCtx+--             ecSecKeyVerify x k+--     assertBool "valid secret key" $ isSuccess ret+--     where+--         key =+--             fromRight undefined $+--                 decodeBase16+--                     "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a" +-- ecPubkeyCreateTest :: Assertion+-- ecPubkeyCreateTest = do+--     pk <- liftIO $+--         useByteString key $ \(s, _) ->+--             allocaBytes 64 $ \k -> do+--                 x <- signCtx+--                 createPubKey x s k+--                 allocaBytes 65 $ \o ->+--                     alloca $ \ol -> do+--                         poke ol 65+--                         rets <- ecPubKeySerialize x o ol k uncompressed+--                         unless (isSuccess rets) $ error "failed to serialize public key"+--                         len <- fromIntegral <$> peek ol+--                         packCStringLen (castPtr o, len)+--     assertEqual "public key matches" pub pk+--     where+--         key =+--             fromRight undefined $+--                 decodeBase16+--                     "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"+--         pub =+--             fromRight undefined $+--                 decodeBase16+--                     "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd447051221\+--                     \3d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf" -parseKey :: Ctx -> ByteString -> IO ByteString-parseKey x bs =-    allocaBytes 64 $ \p ->-        useByteString bs $ \(d, dl) -> do-            ret <- ecPubKeyParse x p d dl-            unless (isSuccess ret) $ error "could not parse public key"-            packByteString (p, 64)+-- ecSecKeyTweakAddTest :: Assertion+-- ecSecKeyTweakAddTest = do+--     (ret, tweaked) <-+--         liftIO $+--             signCtx >>= \x ->+--                 useByteString tweak $ \(w, _) ->+--                     useByteString key $ \(k, _) -> do+--                         ret <- ecSecKeyTweakAdd x k w+--                         tweaked <- packByteString (k, 32)+--                         return (ret, tweaked)+--     assertBool "successful secret key tweak" $ isSuccess ret+--     assertEqual "tweaked keys match" expected tweaked+--     where+--         key =+--             fromRight undefined $+--                 decodeBase16+--                     "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"+--         tweak =+--             fromRight undefined $+--                 decodeBase16+--                     "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"+--         expected =+--             fromRight undefined $+--                 decodeBase16+--                     "ec1e3ce1cefa18a671d51125e2b249688d934b0e28f5d1665384d9b02f929059" +-- ecSecKeyTweakMulTest :: Assertion+-- ecSecKeyTweakMulTest = do+--     (ret, tweaked) <- liftIO $ do+--         x <- contextCreate sign+--         retr <- withEntropy $ contextRandomize x+--         unless (isSuccess retr) $ error "failed to randomize context"+--         useByteString tweak $ \(w, _) -> useByteString key $ \(k, _) -> do+--             ret <- ecSecKeyTweakMul x k w+--             tweaked <- packByteString (k, 32)+--             return (ret, tweaked)+--     assertBool "successful secret key tweak" $ isSuccess ret+--     assertEqual "tweaked keys match" expected tweaked+--     where+--         key =+--             fromRight undefined $+--                 decodeBase16+--                     "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"+--         tweak =+--             fromRight undefined $+--                 decodeBase16+--                     "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"+--         expected =+--             fromRight undefined $+--                 decodeBase16+--                     "a96f5962493acb179f60a86a9785fc7a30e0c39b64c09d24fe064d9aef15e4c0" -ecPubKeyTweakAddTest :: Assertion-ecPubKeyTweakAddTest = do-    (ret, tweaked) <- liftIO $ do-        x <- contextCreate verify-        pk <- copy <$> parseKey x pub-        useByteString tweak $ \(w, _) ->-            useByteString pk $ \(p, _) -> do-                ret <- ecPubKeyTweakAdd x p w-                tweaked <- serializeKey x p-                return (ret, tweaked)-    assertBool "successful secret key tweak" $ isSuccess ret-    assertEqual "tweaked keys match" expected tweaked-    where-        pub =-            fromRight undefined $-                B16.decodeBase16-                    "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd447051221\-                    \3d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"-        tweak =-            fromRight undefined $-                B16.decodeBase16-                    "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"-        expected =-            fromRight undefined $-                B16.decodeBase16-                    "04441c3982b97576646e0df0c96736063df6b42f2ee566d13b9f6424302d1379e518fd\-                    \c87a14c5435bff7a5db4552042cb4120c6b86a4bbd3d0643f3c14ad01368"+-- serializeKey :: Ctx -> Ptr PubKey64 -> IO ByteString+-- serializeKey x p = allocaBytes 72 $ \d -> alloca $ \dl -> do+--     poke dl 72+--     ret <- ecPubKeySerialize x d dl p uncompressed+--     unless (isSuccess ret) $ error "could not serialize public key"+--     len <- peek dl+--     packCStringLen (castPtr d, fromIntegral len) +-- parseKey :: Ctx -> ByteString -> IO ByteString+-- parseKey x bs =+--     allocaBytes 64 $ \p ->+--         useByteString bs $ \(d, dl) -> do+--             ret <- ecPubKeyParse x p d dl+--             unless (isSuccess ret) $ error "could not parse public key"+--             packByteString (p, 64) -ecPubKeyTweakMulTest :: Assertion-ecPubKeyTweakMulTest = do-    (ret, tweaked) <- liftIO $ do-        x <- contextCreate verify-        pk <- copy <$> parseKey x pub-        useByteString tweak $ \(w, _) ->-            useByteString pk $ \(p, _) -> do-                ret <- ecPubKeyTweakMul x p w-                tweaked <- serializeKey x p-                return (ret, tweaked)-    assertBool "successful secret key tweak" $ isSuccess ret-    assertEqual "tweaked keys match" expected tweaked-    where-        pub =-            fromRight undefined $-                B16.decodeBase16-                    "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd447051221\-                    \3d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"-        tweak =-            fromRight undefined $-                B16.decodeBase16-                    "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"-        expected =-            fromRight undefined $-                B16.decodeBase16-                    "04f379dc99cdf5c83e433defa267fbb3377d61d6b779c06a0e4ce29ae3ff5353b12ae4\-                    \9c9d07e7368f2ba5a446c203255ce912322991a2d6a9d5d5761c61ed1845"+-- ecPubKeyTweakAddTest :: Assertion+-- ecPubKeyTweakAddTest = do+--     (ret, tweaked) <- liftIO $ do+--         x <- contextCreate verify+--         pk <- copy <$> parseKey x pub+--         useByteString tweak $ \(w, _) ->+--             useByteString pk $ \(p, _) -> do+--                 ret <- ecPubKeyTweakAdd x p w+--                 tweaked <- serializeKey x p+--                 return (ret, tweaked)+--     assertBool "successful secret key tweak" $ isSuccess ret+--     assertEqual "tweaked keys match" expected tweaked+--     where+--         pub =+--             fromRight undefined $+--                 decodeBase16+--                     "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd447051221\+--                     \3d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"+--         tweak =+--             fromRight undefined $+--                 decodeBase16+--                     "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"+--         expected =+--             fromRight undefined $+--                 decodeBase16+--                     "04441c3982b97576646e0df0c96736063df6b42f2ee566d13b9f6424302d1379e518fd\+--                     \c87a14c5435bff7a5db4552042cb4120c6b86a4bbd3d0643f3c14ad01368" +-- ecPubKeyTweakMulTest :: Assertion+-- ecPubKeyTweakMulTest = do+--     (ret, tweaked) <- liftIO $ do+--         x <- contextCreate verify+--         pk <- copy <$> parseKey x pub+--         useByteString tweak $ \(w, _) ->+--             useByteString pk $ \(p, _) -> do+--                 ret <- ecPubKeyTweakMul x p w+--                 tweaked <- serializeKey x p+--                 return (ret, tweaked)+--     assertBool "successful secret key tweak" $ isSuccess ret+--     assertEqual "tweaked keys match" expected tweaked+--     where+--         pub =+--             fromRight undefined $+--                 decodeBase16+--                     "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd447051221\+--                     \3d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"+--         tweak =+--             fromRight undefined $+--                 decodeBase16+--                     "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"+--         expected =+--             fromRight undefined $+--                 decodeBase16+--                     "04f379dc99cdf5c83e433defa267fbb3377d61d6b779c06a0e4ce29ae3ff5353b12ae4\+--                     \9c9d07e7368f2ba5a446c203255ce912322991a2d6a9d5d5761c61ed1845" -ecPubKeyCombineTest :: Assertion-ecPubKeyCombineTest = do-    (ret, com) <- liftIO $-        allocaBytes 64 $ \p1 ->-            allocaBytes 64 $ \p2 ->-                allocaBytes 64 $ \p3 ->-                    allocaArray 3 $ \a ->-                        allocaBytes 64 $ \p -> do-                            x <- contextCreate verify-                            parse x pub1 p1-                            parse x pub2 p2-                            parse x pub3 p3-                            pokeArray a [p1, p2, p3]-                            ret <- ecPubKeyCombine x p a 3-                            com <- serializeKey x p-                            return (ret, com)-    assertBool "successful key combination" $ isSuccess ret-    assertEqual "combined keys match" expected com-    where-        parse x pub p = useByteString pub $ \(d, dl) -> do-            ret <- ecPubKeyParse x p d dl-            unless (isSuccess ret) $ error "could not parse public key"-        pub1 =-            fromRight undefined $-                B16.decodeBase16-                    "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd447051221\-                    \3d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"-        pub2 =-            fromRight undefined $-                B16.decodeBase16-                    "0487d82042d93447008dfe2af762068a1e53ff394a5bf8f68a045fa642b99ea5d153f5\-                    \77dd2dba6c7ae4cfd7b6622409d7edd2d76dd13a8092cd3af97b77bd2c77"-        pub3 =-            fromRight undefined $-                B16.decodeBase16-                    "049b101edcbe1ee37ff6b2318526a425b629e823d7d8d9154417880595a28000ee3feb\-                    \d908754b8ce4e491aa6fe488b41fb5d4bb3788e33c9ff95a7a9229166d59"-        expected =-            fromRight undefined $-                B16.decodeBase16-                    "043d9a7ec70011efc23c33a7e62d2ea73cca87797e3b659d93bea6aa871aebde56c3bc\-                    \6134ca82e324b0ab9c0e601a6d2933afe7fb5d9f3aae900f5c5dc6e362c8"+-- ecPubKeyCombineTest :: Assertion+-- ecPubKeyCombineTest = do+--     (ret, com) <- liftIO $+--         allocaBytes 64 $ \p1 ->+--             allocaBytes 64 $ \p2 ->+--                 allocaBytes 64 $ \p3 ->+--                     allocaArray 3 $ \a ->+--                         allocaBytes 64 $ \p -> do+--                             x <- contextCreate verify+--                             parse x pub1 p1+--                             parse x pub2 p2+--                             parse x pub3 p3+--                             pokeArray a [p1, p2, p3]+--                             ret <- ecPubKeyCombine x p a 3+--                             com <- serializeKey x p+--                             return (ret, com)+--     assertBool "successful key combination" $ isSuccess ret+--     assertEqual "combined keys match" expected com+--     where+--         parse x pub p = useByteString pub $ \(d, dl) -> do+--             ret <- ecPubKeyParse x p d dl+--             unless (isSuccess ret) $ error "could not parse public key"+--         pub1 =+--             fromRight undefined $+--                 decodeBase16+--                     "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd447051221\+--                     \3d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"+--         pub2 =+--             fromRight undefined $+--                 decodeBase16+--                     "0487d82042d93447008dfe2af762068a1e53ff394a5bf8f68a045fa642b99ea5d153f5\+--                     \77dd2dba6c7ae4cfd7b6622409d7edd2d76dd13a8092cd3af97b77bd2c77"+--         pub3 =+--             fromRight undefined $+--                 decodeBase16+--                     "049b101edcbe1ee37ff6b2318526a425b629e823d7d8d9154417880595a28000ee3feb\+--                     \d908754b8ce4e491aa6fe488b41fb5d4bb3788e33c9ff95a7a9229166d59"+--         expected =+--             fromRight undefined $+--                 decodeBase16+--                     "043d9a7ec70011efc23c33a7e62d2ea73cca87797e3b659d93bea6aa871aebde56c3bc\+--                     \6134ca82e324b0ab9c0e601a6d2933afe7fb5d9f3aae900f5c5dc6e362c8"
+ test/Crypto/Secp256k1Prop.hs view
@@ -0,0 +1,252 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}++module Crypto.Secp256k1Prop where++import Control.Monad (when)+import Crypto.Secp256k1+import Crypto.Secp256k1.Gen+import Data.ByteArray.Sized (sizedByteArray)+import qualified Data.ByteString as BS+import Data.Maybe (fromJust, isJust)+import Data.Void+import Hedgehog+import Hedgehog.Gen hiding (discard, maybe)+import Hedgehog.Range (linear, singleton)+++prop_secKeyParseInvertsSerialize :: Property+prop_secKeyParseInvertsSerialize = property $ do+    sk <- forAll secKeyGen+    case importSecKey $ exportSecKey sk of+        Nothing -> failure+        Just x -> x === sk+++prop_secKeySerializeInvertsParse :: Property+prop_secKeySerializeInvertsParse = property $ do+    bs <- forAll (bytes $ singleton 32)+    case importSecKey bs of+        Nothing -> discard+        Just sk -> exportSecKey sk === bs+++prop_pubKeyXYParseInvertsSerialize :: Property+prop_pubKeyXYParseInvertsSerialize = property $ do+    pk <- forAll pubKeyXYGen+    compress <- forAll $ element [False, True]+    case importPubKeyXY (exportPubKeyXY compress pk) of+        Nothing -> failure+        Just x -> x === pk+++prop_pubKeyXYSerializeInvertsParse :: Property+prop_pubKeyXYSerializeInvertsParse = withDiscards 200 $+    property $ do+        bs <- forAll $ bytes (singleton 32)+        negate <- forAll enumBounded+        let withParity =+                flip BS.cons bs $+                    if negate+                        then 0x03+                        else 0x02+        case importPubKeyXY withParity of+            Nothing -> discard+            Just pk -> exportPubKeyXY True pk === withParity+++prop_pubKeyXOParseInvertsSerialize :: Property+prop_pubKeyXOParseInvertsSerialize = property $ do+    pk <- forAll pubKeyXOGen+    case importPubKeyXO (exportPubKeyXO pk) of+        Nothing -> failure+        Just x -> x === pk+++prop_pubKeyXOSerializeInvertsParse :: Property+prop_pubKeyXOSerializeInvertsParse = property $ do+    bs <- forAll (bytes $ singleton 32)+    case importPubKeyXO bs of+        Nothing -> discard+        Just pk -> exportPubKeyXO pk === bs+++prop_signatureParseInvertsSerialize :: Property+prop_signatureParseInvertsSerialize = property $ do+    sk <- forAll secKeyGen+    bs <- forAll $ bytes (singleton 32)+    sig <- case ecdsaSign sk bs of+        Nothing -> failure+        Just x -> pure x+    exportDer <- forAll $ element [False, True]+    let export = if exportDer then exportSignatureDer else exportSignatureCompact+    let serialized = (export sig)+    annotateShow serialized+    annotateShow (BS.length serialized)+    case importSignature serialized of+        Nothing -> failure+        Just x -> x === sig+++prop_recoverableSignatureParseInvertsSerialize :: Property+prop_recoverableSignatureParseInvertsSerialize = property $ do+    sk <- forAll secKeyGen+    bs <- forAll $ bytes (singleton 32)+    sig <- case ecdsaSignRecoverable sk bs of+        Nothing -> failure+        Just x -> pure x+    let serialized = (exportRecoverableSignature sig)+    annotateShow serialized+    annotateShow (BS.length serialized)+    case importRecoverableSignature serialized of+        Nothing -> failure+        Just x -> x === sig+++prop_validSecKeyImpliesValidTweak :: Property+prop_validSecKeyImpliesValidTweak = property $ do+    sk <- forAll secKeyGen+    assert $ isJust $ importTweak (exportSecKey sk)+++prop_ecdsaSignaturesProducedAreValid :: Property+prop_ecdsaSignaturesProducedAreValid = property $ do+    sk <- forAll secKeyGen+    msg <- forAll $ bytes (singleton 32)+    case ecdsaSign sk msg of+        Nothing -> failure+        Just sig -> assert $ ecdsaVerify msg (derivePubKey sk) sig+++prop_ecdsaRecoverableSignaturesProducedAreValid :: Property+prop_ecdsaRecoverableSignaturesProducedAreValid = property $ do+    sk <- forAll secKeyGen+    msg <- forAll $ bytes (singleton 32)+    case ecdsaSignRecoverable sk msg of+        Nothing -> failure+        Just recSig -> assert $ ecdsaVerify msg (derivePubKey sk) (recSigToSig recSig)+++prop_ecdsaSignatureValidityPreservedOverSerialization :: Property+prop_ecdsaSignatureValidityPreservedOverSerialization = property $ do+    sk <- forAll secKeyGen+    msg <- forAll $ bytes (singleton 32)+    let sig = fromJust $ ecdsaSign sk msg+    useDer <- forAll enumBounded+    let export =+            if useDer+                then exportSignatureDer+                else exportSignatureCompact+    let serialized = export sig+    let parsed = fromJust (importSignature serialized)+    assert $ ecdsaVerify msg (derivePubKey sk) parsed+++prop_ecdsaRecoverableSignatureProducesValidPubKey :: Property+prop_ecdsaRecoverableSignatureProducesValidPubKey = property $ do+    sk <- forAll secKeyGen+    msg <- forAll $ bytes (singleton 32)+    case ecdsaRecover (fromJust $ ecdsaSignRecoverable sk msg) msg of+        Nothing -> failure+        Just pk -> pk === derivePubKey sk+++prop_ecdsaRecoverableSignatureIdentity :: Property+prop_ecdsaRecoverableSignatureIdentity = property $ do+    sk <- forAll secKeyGen+    msg <- forAll $ bytes (singleton 32)+    case ecdsaSignRecoverable sk msg of+        Nothing -> failure+        Just sig -> Just (recSigToSig sig) === ecdsaSign sk msg+++prop_keyPairIdentities :: Property+prop_keyPairIdentities = property $ do+    sk <- forAll secKeyGen+    let kp = keyPairCreate sk+    keyPairSecKey kp === sk+    keyPairPubKeyXY kp === derivePubKey sk+    keyPairPubKeyXO kp === xyToXO (derivePubKey sk)+++prop_tweakDistributesOverPubKeyDerivation :: Property+prop_tweakDistributesOverPubKeyDerivation = property $ do+    sk <- forAll secKeyGen+    tweak <- forAll tweakGen+    (derivePubKey <$> secKeyTweakAdd sk tweak) === pubKeyTweakAdd (derivePubKey sk) tweak+    (derivePubKey <$> secKeyTweakMul sk tweak) === pubKeyTweakMul (derivePubKey sk) tweak+++prop_pubKeyCombineOrderIndependent :: Property+prop_pubKeyCombineOrderIndependent = property $ do+    ls <- forAll $ list (linear 0 20) pubKeyXYGen+    ls' <- forAll $ shuffle ls+    pubKeyCombine ls === pubKeyCombine ls'+++prop_negationDistributesOverPubKeyDerivation :: Property+prop_negationDistributesOverPubKeyDerivation = property $ do+    sk <- forAll secKeyGen+    derivePubKey (secKeyNegate sk) === pubKeyNegate (derivePubKey sk)+++prop_secKeyDoubleNegationIdentity :: Property+prop_secKeyDoubleNegationIdentity = property $ do+    sk <- forAll secKeyGen+    (secKeyNegate . secKeyNegate) sk === sk+++prop_pubKeyDoubleNegationIdentity :: Property+prop_pubKeyDoubleNegationIdentity = property $ do+    pk <- forAll pubKeyXYGen+    (pubKeyNegate . pubKeyNegate) pk === pk+++prop_schnorrSignaturesProducedAreValid :: Property+prop_schnorrSignaturesProducedAreValid = property $ do+    sk <- forAll secKeyGen+    msg <- forAll $ bytes (singleton 32)+    let kp = keyPairCreate sk+    case schnorrSign kp msg of+        Nothing -> failure+        Just sig -> assert $ schnorrVerify (fst $ keyPairPubKeyXO kp) msg sig+++prop_pubKeyCombineTweakIdentity :: Property+prop_pubKeyCombineTweakIdentity = property $ do+    sk <- forAll secKeyGen+    sk' <- forAll secKeyGen+    pubKeyCombine [derivePubKey sk, derivePubKey sk'] === pubKeyTweakAdd (derivePubKey sk) (fromJust $ importTweak (exportSecKey sk'))+++prop_ecdhIdentity :: Property+prop_ecdhIdentity = property $ do+    sk <- forAll secKeyGen+    sk' <- forAll secKeyGen+    ecdh sk (derivePubKey sk') === ecdh sk' (derivePubKey sk)+++prop_ecdsaSignaturesUnforgeable :: Property+prop_ecdsaSignaturesUnforgeable = property $ do+    sk <- forAll secKeyGen+    pk <- forAll pubKeyXYGen+    when (pk == derivePubKey sk) discard+    msg <- forAll $ bytes (singleton 32)+    case ecdsaSign sk msg of+        Nothing -> failure+        Just sig -> assert . not $ ecdsaVerify msg pk sig+++prop_schnorrSignaturesUnforgeable :: Property+prop_schnorrSignaturesUnforgeable = property $ do+    sk <- forAll secKeyGen+    let kp = keyPairCreate sk+    pk <- forAll pubKeyXOGen+    msg <- forAll $ bytes (singleton 32)+    case schnorrSign kp msg of+        Nothing -> failure+        Just sig -> assert . not $ schnorrVerify pk msg sig+++tests :: Group+tests = $$(discover)
test/Crypto/Secp256k1Spec.hs view
@@ -1,248 +1,228 @@ module Crypto.Secp256k1Spec (spec) where -import           Control.Monad.Par-import qualified Control.Monad.Par       as P-import           Crypto.Secp256k1-import qualified Data.ByteString         as BS-import qualified Data.ByteString.Base16  as B16-import qualified Data.ByteString.Char8   as B8-import           Data.Either             (fromRight)-import           Data.Maybe              (fromMaybe, isNothing)-import           Data.String             (fromString)-import           Data.String.Conversions (cs)-import           Test.HUnit              (Assertion, assertEqual)-import           Test.Hspec-import           Test.QuickCheck+-- import Control.Monad.Par+-- import qualified Control.Monad.Par as P+import Crypto.Secp256k1+import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as B8+import Data.Either (fromRight)+import Data.Maybe (fromMaybe, isNothing)+import Data.String (fromString)+import Test.HUnit (Assertion, assertEqual)+import Test.Hspec + spec :: Spec spec = do-    describe "signatures" $ do-        it "signs message" $-            property signMsgTest-        it "signs messages in parallel" $-            property signMsgParTest-        it "detects bad signature" $-            property badSignatureTest-        it "normalizes signatures" $-            property normalizeSigTest-    describe "serialization" $ do-        it "serializes public key" $-            property serializePubKeyTest-        it "serializes public keys in parallel" $-            property parSerializePubKeyTest-        it "serializes DER signature" $-            property serializeSigTest-        it "serializes DER signatures in parallel" $-            property parSerializeSigTest-        it "serializes compact signature" $-            property serializeCompactSigTest-        it "serialize secret key" $-            property serializeSecKeyTest-        it "shows and reads public key" $-            property (showRead :: PubKey -> Bool)-        it "shows and reads secret key" $-            property (showRead :: SecKey -> Bool)-        it "shows and reads tweak" $-            property (showReadTweak :: SecKey -> Bool)-        it "shows and reads signature" $-            property (showReadSig :: (SecKey, Msg) -> Bool)-        it "shows and reads message" $-            property (showRead :: Msg -> Bool)-        it "reads public key from string" $-            property isStringPubKey-        it "reads secret key from string" $-            property isStringSecKey-        it "reads signature from string" $-            property isStringSig-        it "reads message from string" $-            property isStringMsg-        it "reads tweak from string" $-            property isStringTweak-    describe "tweaks" $ do-        it "add secret key" $ property tweakAddSecKeyTest-        it "multiply secret key" $ property tweakMulSecKeyTest-        it "add public key" $ property tweakAddPubKeyTest-        it "multiply public key" $ property tweakMulPubKeyTest-        it "combine public keys" $ property combinePubKeyTest-        it "can't combine 0 public keys" $ property combinePubKeyEmptyListTest-        it "negates tweak" $ property negateTweakTest--hexToBytes :: String -> BS.ByteString-hexToBytes = fromRight undefined . B16.decodeBase16 . B8.pack--isStringPubKey :: (PubKey, Bool) -> Bool-isStringPubKey (k, c) = k == fromString (cs hex) where-    hex = B16.encodeBase16 $ exportPubKey c k--isStringSig :: (SecKey, Msg) -> Bool-isStringSig (k, m) = g == fromString (cs hex) where-    g = signMsg k m-    hex = B16.encodeBase16 $ exportSig g--isStringMsg :: Msg -> Bool-isStringMsg m = m == fromString (cs m') where-    m' = B16.encodeBase16 $ getMsg m+    pure () -isStringSecKey :: SecKey -> Bool-isStringSecKey k = k == fromString (cs hex) where-    hex = B16.encodeBase16 $ getSecKey k+--     describe "tweaks" $ do+--         it "add secret key" tweakAddSecKeyTest+--         it "multiply secret key" tweakMulSecKeyTest+--         it "add public key" tweakAddPubKeyTest+--         it "multiply public key" tweakMulPubKeyTest+--         it "combine public keys" combinePubKeyTest+--         it "can't combine 0 public keys" combinePubKeyEmptyListTest+--         it "negates tweak" negateTweakTest -isStringTweak :: SecKey -> Bool-isStringTweak k = t == fromString (cs hex) where-    t = fromMaybe e . tweak $ getSecKey k-    hex = B16.encodeBase16 $ getTweak t-    e = error "Could not extract tweak from secret key"+-- hexToBytes :: String -> BS.ByteString+-- hexToBytes = fromRight undefined . decodeBase16 . B8.pack -showReadTweak :: SecKey -> Bool-showReadTweak k = showRead t where-    t = tweak $ getSecKey k+-- 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+-- 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+-- 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+-- signMsgTest :: (Msg, SecKey) -> Bool+-- signMsgTest (fm, fk) = verifySig fp fg fm+--     where+--         fp = derivePubKey fk+--         fg = signMsg fk fm -signMsgParTest :: [(Msg, SecKey)] -> Bool-signMsgParTest xs = P.runPar $ do-    ys <- mapM (P.spawnP . signMsgTest) xs-    and <$> mapM P.get ys+-- signMsgParTest :: [(Msg, SecKey)] -> Bool+-- signMsgParTest xs = P.runPar $ do+--     ys <- mapM (P.spawnP . signMsgTest) xs+--     and <$> mapM P.get ys -badSignatureTest :: (Msg, SecKey, PubKey) -> Bool-badSignatureTest (fm, fk, fp) = not $ verifySig fp fg fm where-    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) = isNothing sig where-    fg = signMsg fk fm-    sig = normalizeSig fg+-- normalizeSigTest :: (Msg, SecKey) -> Bool+-- normalizeSigTest (fm, fk) = isNothing sig+--     where+--         fg = signMsg fk fm+--         sig = normalizeSig fg -serializePubKeyTest :: (PubKey, Bool) -> Bool-serializePubKeyTest (fp, b) =-    case importPubKey $ exportPubKey b fp of-        Just fp' -> fp == fp'-        Nothing  -> False+-- serializePubKeyTest :: (PubKey, Bool) -> Bool+-- serializePubKeyTest (fp, b) =+--     case importPubKey $ exportPubKey b fp of+--         Just fp' -> fp == fp'+--         Nothing -> False -parSerializePubKeyTest :: [(PubKey, Bool)] -> Bool-parSerializePubKeyTest ps = runPar $ do-    as <- mapM (spawnP . serializePubKeyTest) ps-    and <$> mapM get as+-- parSerializePubKeyTest :: [(PubKey, Bool)] -> Bool+-- parSerializePubKeyTest ps = runPar $ do+--     as <- mapM (spawnP . serializePubKeyTest) ps+--     and <$> mapM get as -serializeSigTest :: (Msg, SecKey) -> Bool-serializeSigTest (fm, fk) =-    case importSig $ exportSig fg of-        Just fg' -> fg == fg'-        Nothing  -> False-  where-    fg = signMsg fk fm+-- serializeSigTest :: (Msg, SecKey) -> Bool+-- serializeSigTest (fm, fk) =+--     case importSig $ exportSig fg of+--         Just fg' -> fg == fg'+--         Nothing -> False+--     where+--         fg = signMsg fk fm -parSerializeSigTest :: [(Msg, SecKey)] -> Bool-parSerializeSigTest ms = runPar $ do-    as <- mapM (spawnP . serializeSigTest) ms-    and <$> mapM get as+-- parSerializeSigTest :: [(Msg, SecKey)] -> Bool+-- parSerializeSigTest ms = runPar $ do+--     as <- mapM (spawnP . serializeSigTest) ms+--     and <$> mapM get as -serializeCompactSigTest :: (Msg, SecKey) -> Bool-serializeCompactSigTest (fm, fk) =-    case importCompactSig $ exportCompactSig 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+-- 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 $ hexToBytes-            "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"-        twk <- tweak $ hexToBytes-            "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"-        tweakAddSecKey key twk-    expected = secKey $ hexToBytes-        "ec1e3ce1cefa18a671d51125e2b249688d934b0e28f5d1665384d9b02f929059"+-- tweakAddSecKeyTest :: Assertion+-- tweakAddSecKeyTest =+--     assertEqual "tweaked keys match" expected tweaked+--     where+--         tweaked = do+--             key <-+--                 secKey $+--                     hexToBytes+--                         "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"+--             twk <-+--                 tweak $+--                     hexToBytes+--                         "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"+--             tweakAddSecKey key twk+--         expected =+--             secKey $+--                 hexToBytes+--                     "ec1e3ce1cefa18a671d51125e2b249688d934b0e28f5d1665384d9b02f929059" -tweakMulSecKeyTest :: Assertion-tweakMulSecKeyTest =-    assertEqual "tweaked keys match" expected tweaked-  where-    tweaked = do-        key <- secKey $ hexToBytes-            "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"-        twk <- tweak $ hexToBytes-            "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"-        tweakMulSecKey key twk-    expected = secKey $ hexToBytes-        "a96f5962493acb179f60a86a9785fc7a30e0c39b64c09d24fe064d9aef15e4c0"+-- tweakMulSecKeyTest :: Assertion+-- tweakMulSecKeyTest =+--     assertEqual "tweaked keys match" expected tweaked+--     where+--         tweaked = do+--             key <-+--                 secKey $+--                     hexToBytes+--                         "f65255094d7773ed8dd417badc9fc045c1f80fdc5b2d25172b031ce6933e039a"+--             twk <-+--                 tweak $+--                     hexToBytes+--                         "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"+--             tweakMulSecKey key twk+--         expected =+--             secKey $+--                 hexToBytes+--                     "a96f5962493acb179f60a86a9785fc7a30e0c39b64c09d24fe064d9aef15e4c0" -tweakAddPubKeyTest :: Assertion-tweakAddPubKeyTest =-    assertEqual "tweaked keys match" expected tweaked-  where-    tweaked = do-        pub <- importPubKey $ hexToBytes-            "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd4470512213d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"-        twk <- tweak $ hexToBytes-            "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"-        tweakAddPubKey pub twk-    expected = importPubKey $ hexToBytes-        "04441c3982b97576646e0df0c96736063df6b42f2ee566d13b9f6424302d1379e518fdc87a14c5435bff7a5db4552042cb4120c6b86a4bbd3d0643f3c14ad01368"+-- tweakAddPubKeyTest :: Assertion+-- tweakAddPubKeyTest =+--     assertEqual "tweaked keys match" expected tweaked+--     where+--         tweaked = do+--             pub <-+--                 importPubKey $+--                     hexToBytes+--                         "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd4470512213d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"+--             twk <-+--                 tweak $+--                     hexToBytes+--                         "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"+--             tweakAddPubKey pub twk+--         expected =+--             importPubKey $+--                 hexToBytes+--                     "04441c3982b97576646e0df0c96736063df6b42f2ee566d13b9f6424302d1379e518fdc87a14c5435bff7a5db4552042cb4120c6b86a4bbd3d0643f3c14ad01368" -tweakMulPubKeyTest :: Assertion-tweakMulPubKeyTest =-    assertEqual "tweaked keys match" expected tweaked-  where-    tweaked = do-        pub <- importPubKey $ hexToBytes-            "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd4470512213d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"-        twk <- tweak $ hexToBytes-            "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"-        tweakMulPubKey pub twk-    expected = importPubKey $ hexToBytes-        "04f379dc99cdf5c83e433defa267fbb3377d61d6b779c06a0e4ce29ae3ff5353b12ae49c9d07e7368f2ba5a446c203255ce912322991a2d6a9d5d5761c61ed1845"+-- tweakMulPubKeyTest :: Assertion+-- tweakMulPubKeyTest =+--     assertEqual "tweaked keys match" expected tweaked+--     where+--         tweaked = do+--             pub <-+--                 importPubKey $+--                     hexToBytes+--                         "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd4470512213d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"+--             twk <-+--                 tweak $+--                     hexToBytes+--                         "f5cbe7d88182a4b8e400f96b06128921864a18187d114c8ae8541b566c8ace00"+--             tweakMulPubKey pub twk+--         expected =+--             importPubKey $+--                 hexToBytes+--                     "04f379dc99cdf5c83e433defa267fbb3377d61d6b779c06a0e4ce29ae3ff5353b12ae49c9d07e7368f2ba5a446c203255ce912322991a2d6a9d5d5761c61ed1845" -combinePubKeyTest :: Assertion-combinePubKeyTest =-    assertEqual "combined keys match" expected combined-  where-    combined = do-        pub1 <- importPubKey $ hexToBytes-            "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd4470512213d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"-        pub2 <- importPubKey $ hexToBytes-            "0487d82042d93447008dfe2af762068a1e53ff394a5bf8f68a045fa642b99ea5d153f577dd2dba6c7ae4cfd7b6622409d7edd2d76dd13a8092cd3af97b77bd2c77"-        pub3 <- importPubKey $ hexToBytes-            "049b101edcbe1ee37ff6b2318526a425b629e823d7d8d9154417880595a28000ee3febd908754b8ce4e491aa6fe488b41fb5d4bb3788e33c9ff95a7a9229166d59"-        combinePubKeys [pub1, pub2, pub3]-    expected = importPubKey $ hexToBytes-        "043d9a7ec70011efc23c33a7e62d2ea73cca87797e3b659d93bea6aa871aebde56c3bc6134ca82e324b0ab9c0e601a6d2933afe7fb5d9f3aae900f5c5dc6e362c8"+-- combinePubKeyTest :: Assertion+-- combinePubKeyTest =+--     assertEqual "combined keys match" expected combined+--     where+--         combined = do+--             pub1 <-+--                 importPubKey $+--                     hexToBytes+--                         "04dded4203dac96a7e85f2c374a37ce3e9c9a155a72b64b4551b0bfe779dd4470512213d5ed790522c042dee8e85c4c0ec5f96800b72bc5940c8bc1c5e11e4fcbf"+--             pub2 <-+--                 importPubKey $+--                     hexToBytes+--                         "0487d82042d93447008dfe2af762068a1e53ff394a5bf8f68a045fa642b99ea5d153f577dd2dba6c7ae4cfd7b6622409d7edd2d76dd13a8092cd3af97b77bd2c77"+--             pub3 <-+--                 importPubKey $+--                     hexToBytes+--                         "049b101edcbe1ee37ff6b2318526a425b629e823d7d8d9154417880595a28000ee3febd908754b8ce4e491aa6fe488b41fb5d4bb3788e33c9ff95a7a9229166d59"+--             combinePubKeys [pub1, pub2, pub3]+--         expected =+--             importPubKey $+--                 hexToBytes+--                     "043d9a7ec70011efc23c33a7e62d2ea73cca87797e3b659d93bea6aa871aebde56c3bc6134ca82e324b0ab9c0e601a6d2933afe7fb5d9f3aae900f5c5dc6e362c8" -combinePubKeyEmptyListTest :: Assertion-combinePubKeyEmptyListTest =-    assertEqual "empty pubkey list must return Nothing" expected combined-  where-    expected = Nothing-    combined = combinePubKeys []+-- combinePubKeyEmptyListTest :: Assertion+-- combinePubKeyEmptyListTest =+--     assertEqual "empty pubkey list must return Nothing" expected combined+--     where+--         expected = Nothing+--         combined = combinePubKeys [] -negateTweakTest :: Assertion-negateTweakTest =-    assertEqual "can recover secret key 1 after adding tweak 1" oneKey subtracted-  where-    Just oneKey = secKey $ fromRight undefined $ B16.decodeBase16 $ B8.pack-        "0000000000000000000000000000000000000000000000000000000000000001"-    Just oneTwk = tweak $ fromRight undefined $ B16.decodeBase16 $ B8.pack-        "0000000000000000000000000000000000000000000000000000000000000001"-    Just minusOneTwk = tweakNegate oneTwk-    Just twoKey = tweakAddSecKey oneKey oneTwk-    Just subtracted = tweakAddSecKey twoKey minusOneTwk+-- negateTweakTest :: Assertion+-- negateTweakTest =+--     assertEqual "can recover secret key 1 after adding tweak 1" oneKey subtracted+--     where+--         Just oneKey =+--             secKey $+--                 fromRight undefined $+--                     decodeBase16 $+--                         B8.pack+--                             "0000000000000000000000000000000000000000000000000000000000000001"+--         Just oneTwk =+--             tweak $+--                 fromRight undefined $+--                     decodeBase16 $+--                         B8.pack+--                             "0000000000000000000000000000000000000000000000000000000000000001"+--         Just minusOneTwk = tweakNegate oneTwk+--         Just twoKey = tweakAddSecKey oneKey oneTwk+--         Just subtracted = tweakAddSecKey twoKey minusOneTwk
+ test/Main.hs view
@@ -0,0 +1,18 @@+module Main where++import qualified Crypto.Secp256k1Prop as Secp256k1Prop+import GHC.IO.Encoding (setLocaleEncoding, utf8)+import Hedgehog (checkSequential)+import Hedgehog.Main+import qualified Spec+import Test.Hspec.Formatters+import Test.Hspec.Runner (Config (..), defaultConfig, hspecWith)+++main :: IO ()+main = do+    setLocaleEncoding utf8+    hspecWith defaultConfig{configFormatter = Just progress} Spec.spec+    defaultMain $+        [ checkSequential Secp256k1Prop.tests+        ]
test/Spec.hs view
@@ -1,1 +1,9 @@-{-# OPTIONS_GHC -F -pgmF hspec-discover #-}+module Spec where++import qualified Crypto.Secp256k1Spec as Secp256k1+import Test.Hspec+++spec :: Spec+spec = do+    Secp256k1.spec
+ test/Util.hs view
@@ -0,0 +1,12 @@+module Util where++import qualified Data.ByteArray.Encoding as BA+import Data.ByteString+++decodeBase16 :: ByteString -> Either String ByteString+decodeBase16 = BA.convertFromBase BA.Base16+++encodeBase16 :: ByteString -> ByteString+encodeBase16 = BA.convertToBase BA.Base16