csecp256k1

Haskell FFI bindings to bitcoin-core/secp256k1 (docs.ppad.tech/csecp256k1).
git clone git://git.ppad.tech/csecp256k1.git
Log | Files | Refs | README | LICENSE

Main.hs (8195B)


      1 {-# LANGUAGE OverloadedStrings #-}
      2 
      3 module Main where
      4 
      5 import qualified Data.ByteString as BS
      6 import Crypto.Secp256k1
      7 import Test.Tasty
      8 import Test.Tasty.HUnit
      9 
     10 main :: IO ()
     11 main = defaultMain units
     12 
     13 units :: TestTree
     14 units = testGroup "unit tests" [
     15     parse_pub_test
     16   , serialize_pub_test
     17   , serialize_pub_u_test
     18   , derive_pub_test
     19   , tweak_pub_add_test
     20   , tweak_pub_mul_test
     21   , tweak_sec_add_test
     22   , tweak_sec_mul_test
     23   , parse_der_test
     24   , serialize_der_test
     25   , compact_test
     26   , parse_xonly_test
     27   , serialize_xonly_test
     28   , keypair_test
     29   , sign_test
     30   , verify_test
     31   , sign_schnorr_test
     32   , verify_schnorr_test
     33   ]
     34 
     35 parse_pub_test :: TestTree
     36 parse_pub_test = testCase "parse_pub (success)" $
     37   wcontext $ \tex -> do
     38     -- throws on failure, so any return implies success
     39     _ <- parse_pub tex _PUB_COMPRESSED
     40     assertBool "success" True
     41 
     42 serialize_pub_test :: TestTree
     43 serialize_pub_test = testCase "serialize_pub (success)" $
     44   wcontext $ \tex -> do
     45     par <- parse_pub tex _PUB_COMPRESSED
     46     pub <- serialize_pub tex par
     47     assertEqual "success" pub _PUB_COMPRESSED
     48 
     49 serialize_pub_u_test :: TestTree
     50 serialize_pub_u_test = testCase "serialize_pub_u (success)" $
     51   wcontext $ \tex -> do
     52     par <- parse_pub tex _PUB_UNCOMPRESSED
     53     pub <- serialize_pub_u tex par
     54     assertEqual "success" pub _PUB_UNCOMPRESSED
     55 
     56 derive_pub_test :: TestTree
     57 derive_pub_test = testCase "derive_pub (success)" $
     58   wcontext $ \tex -> do
     59     -- throws on failure, so any return implies success
     60     _ <- derive_pub tex _SEC
     61     assertBool "success" True
     62 
     63 tweak_pub_add_test :: TestTree
     64 tweak_pub_add_test =
     65   testCase "tweak_pub_add (success)" $
     66     wcontext $ \tex -> do
     67       pub <- parse_pub tex _PUB_COMPRESSED
     68       add <- tweak_pub_add tex pub _TWEAK
     69       eek <- serialize_pub_u tex add
     70       assertEqual "success" eek _PUB_ADD_TWEAKED
     71 
     72 tweak_pub_mul_test :: TestTree
     73 tweak_pub_mul_test =
     74   testCase "tweak_pub_mul (success)" $
     75     wcontext $ \tex -> do
     76       pub <- parse_pub tex _PUB_COMPRESSED
     77       add <- tweak_pub_mul tex pub _TWEAK
     78       eek <- serialize_pub_u tex add
     79       assertEqual "success" eek _PUB_MUL_TWEAKED
     80 
     81 tweak_sec_add_test :: TestTree
     82 tweak_sec_add_test =
     83   testCase "tweak_sec_add (success)" $
     84     wcontext $ \tex -> do
     85       eek <- tweak_sec_add tex _SEC _TWEAK
     86       assertEqual "success" eek _SEC_ADD_TWEAKED
     87 
     88 tweak_sec_mul_test :: TestTree
     89 tweak_sec_mul_test =
     90   testCase "tweak_sec_mul (success)" $
     91     wcontext $ \tex -> do
     92       eek <- tweak_sec_mul tex _SEC _TWEAK
     93       assertEqual "success" eek _SEC_MUL_TWEAKED
     94 
     95 parse_der_test :: TestTree
     96 parse_der_test =
     97   testCase "parse_der (success)" $
     98     wcontext $ \tex -> do
     99       -- throws on failure, so any return implies success
    100       _ <- parse_der tex _DER
    101       assertBool "success" True
    102 
    103 serialize_der_test :: TestTree
    104 serialize_der_test =
    105   testCase "serialize_der (success)" $
    106     wcontext $ \tex -> do
    107       par <- parse_der tex _DER
    108       der <- serialize_der tex par
    109       assertEqual "success" der _DER
    110 
    111 -- joint parse, serialize test
    112 compact_test :: TestTree
    113 compact_test =
    114   testCase "{parse, serialize}_compact (success)" $
    115     wcontext $ \tex -> do
    116       sig <- parse_der tex _DER
    117       com <- serialize_compact tex sig
    118       par <- parse_compact tex com
    119       der <- serialize_der tex par
    120       assertEqual "success" der _DER
    121 
    122 parse_xonly_test :: TestTree
    123 parse_xonly_test =
    124   testCase "parse_xonly (success)" $ do
    125     wcontext $ \tex -> do
    126       pux <- parse_xonly tex _PUB_XONLY
    127       pub <- serialize_xonly tex pux
    128       assertEqual "success" pub _PUB_XONLY
    129 
    130 serialize_xonly_test :: TestTree
    131 serialize_xonly_test =
    132   testCase "serialize_xonly (success)" $
    133     wcontext $ \tex -> do
    134       pub <- parse_pub tex _PUB_COMPRESSED
    135       key <- xonly tex pub
    136       pux <- serialize_xonly tex key
    137       assertEqual "success" pux _PUB_XONLY
    138 
    139 keypair_test :: TestTree
    140 keypair_test =
    141   testCase "keypair (success)" $ do
    142     wcontext $ \tex -> do
    143       per <- keypair tex _SEC
    144       sec <- keypair_sec tex per
    145       pub <- keypair_pub tex per
    146       ser <- serialize_pub tex pub
    147       assertEqual "success" sec _SEC
    148       assertEqual "success" ser _PUB_COMPRESSED
    149 
    150 sign_test :: TestTree
    151 sign_test = testCase "sign (success)" $
    152   wcontext $ \tex -> do
    153     sig <- sign tex _SEC _HAS
    154     der <- serialize_der tex sig
    155     assertEqual "success" _DER der
    156 
    157 verify_test :: TestTree
    158 verify_test = testCase "verify (success)" $
    159   wcontext $ \tex -> do
    160     pub <- parse_pub tex _PUB_UNCOMPRESSED
    161     sig <- parse_der tex _DER
    162     suc <- verify tex pub _HAS sig
    163     assertBool "success" suc
    164 
    165 sign_schnorr_test :: TestTree
    166 sign_schnorr_test = testCase "sign_schnorr (success)" $
    167   wcontext $ \tex -> do
    168     let enn = BS.replicate 32 0
    169     sig <- sign_schnorr tex _HAS _SEC enn
    170     assertEqual "success" sig _SIG_SCHNORR
    171 
    172 verify_schnorr_test :: TestTree
    173 verify_schnorr_test = testCase "verify_schnorr (success)" $
    174   wcontext $ \tex -> do
    175     pub <- parse_pub tex _PUB_UNCOMPRESSED
    176     suc <- verify_schnorr tex pub _HAS _SIG_SCHNORR
    177     assertBool "success" suc
    178 
    179 ecdh_test :: TestTree
    180 ecdh_test = testCase "ecdh (success)" $
    181   wcontext $ \tex -> do
    182     pub <- parse_pub tex _PUB_COMPRESSED
    183     -- throws on failure, so any return implies success
    184     _ <- ecdh tex pub _SEC
    185     assertBool "success" True
    186 
    187 -- test inputs
    188 
    189 -- mostly grabbed from haskoin/secp256k1-haskell
    190 
    191 -- DER-encoded signature
    192 _DER :: BS.ByteString
    193 _DER = mconcat [
    194     "0E\STX!\NUL\245\STX\191\160z\244>~\242ea\139\r\146\154v\EM\238\SOH\214"
    195   , "\NAK\SO7\235n\170\242\200\189\&7\251\"\STX o\EOT\NAK\171\SO\154\151z"
    196   , "\253x\178\194n\243\155\&9R\tm1\159\212\177\SOH\199h\173l\DC3.0E"
    197   ]
    198 
    199 -- a 32-byte message hash
    200 _HAS :: BS.ByteString
    201 _HAS = mconcat [
    202     "\245\203\231\216\129\130\164\184\228\NUL\249k\ACK\DC2\137!\134J"
    203   , "\CAN\CAN}\DC1L\138\232T\ESCVl\138\206\NUL"
    204   ]
    205 
    206 -- a 32-byte secret key
    207 _SEC :: BS.ByteString
    208 _SEC = mconcat [
    209     "\246RU\tMws\237\141\212\ETB\186\220\159\192E\193\248\SI\220[-%\ETB"
    210   , "+\ETX\FS\230\147>\ETX\154"
    211   ]
    212 
    213 -- 32 bytes
    214 _TWEAK :: BS.ByteString
    215 _TWEAK = mconcat [
    216     "\245\203\231\216\129\130\164\184\228\NUL\249k\ACK\DC2\137!\134J"
    217   , "\CAN\CAN}\DC1L\138\232T\ESCVl\138\206\NUL"
    218   ]
    219 
    220 -- _PUB add-tweaked with _TWEAK
    221 _PUB_ADD_TWEAKED :: BS.ByteString
    222 _PUB_ADD_TWEAKED = mconcat [
    223     "\EOTD\FS9\130\185uvdn\r\240\201g6\ACK=\246\180/.\229f\209;\159d$0-"
    224   , "\DC3y\229\CAN\253\200z\DC4\197C[\255z]\180U B\203A \198\184jK\189="
    225   , "\ACKC\243\193J\208\DC3h"
    226   ]
    227 
    228 -- _PUB mul-tweaked with _TWEAK
    229 _PUB_MUL_TWEAKED :: BS.ByteString
    230 _PUB_MUL_TWEAKED = mconcat [
    231     "\EOT\243y\220\153\205\245\200>C=\239\162g\251\179\&7}a\214\183y"
    232   , "\192j\SOL\226\154\227\255SS\177*\228\156\157\a\231\&6\143+\165"
    233   , "\164F\194\ETX%\\\233\DC22)\145\162\214\169\213\213v\FSa\237\CANE"
    234   ]
    235 
    236 -- _SEC add-tweaked with _TWEAK
    237 _SEC_ADD_TWEAKED :: BS.ByteString
    238 _SEC_ADD_TWEAKED = mconcat [
    239     "\236\RS<\225\206\250\CAN\166q\213\DC1%\226\178Ih\141\147K\SO(\245"
    240   , "\209fS\132\217\176/\146\144Y"
    241   ]
    242 
    243 -- _SEC mul-tweaked with _TWEAK
    244 _SEC_MUL_TWEAKED :: BS.ByteString
    245 _SEC_MUL_TWEAKED = mconcat [
    246     "\169oYbI:\203\ETB\159`\168j\151\133\252z0\224\195\155d\192\157$\254"
    247   , "\ACKM\154\239\NAK\228\192"
    248   ]
    249 
    250 -- 33-byte (compressed) public key
    251 _PUB_COMPRESSED :: BS.ByteString
    252 _PUB_COMPRESSED = mconcat [
    253     "\ETX\221\237B\ETX\218\201j~\133\242\195t\163|\227\233\201\161U"
    254   , "\167+d\180U\ESC\v\254w\157\212G\ENQ"
    255   ]
    256 
    257 -- 65-byte (uncompressed) public key
    258 _PUB_UNCOMPRESSED :: BS.ByteString
    259 _PUB_UNCOMPRESSED = mconcat [
    260     "\EOT\221\237B\ETX\218\201j~\133\242\195t\163|\227\233\201\161U\167"
    261   , "+d\180U\ESC\v\254w\157\212G\ENQ\DC2!=^\215\144R,\EOT-\238\142\133"
    262   , "\196\192\236_\150\128\vr\188Y@\200\188\FS^\DC1\228\252\191"
    263   ]
    264 
    265 -- 32-byte x-only pubkey
    266 _PUB_XONLY :: BS.ByteString
    267 _PUB_XONLY = mconcat [
    268     "\221\237B\ETX\218\201j~\133\242\195t\163|\227\233\201\161U\167+d"
    269   , "\180U\ESC\v\254w\157\212G\ENQ"
    270   ]
    271 
    272 -- 64-byte schnorr signature
    273 _SIG_SCHNORR :: BS.ByteString
    274 _SIG_SCHNORR  = mconcat [
    275     "\214\185AtJ\189\250Gp\NAK2\221\DC2[\182\209\192j{\140^\222R\NUL~"
    276   , "\139d@<\138\163rh\247\152\r\228\175\236\219\156\151\214~\135\&7"
    277   , "\225\&6\234\220;\164R\191\170\186\243\NAK\147\f\144\156ez"
    278   ]
    279