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 (19674B)


      1 {-# LANGUAGE OverloadedStrings  #-}
      2 {-# LANGUAGE ViewPatterns  #-}
      3 
      4 module Main where
      5 
      6 import Control.Monad (when)
      7 import Control.Exception (Exception, throwIO)
      8 import Crypto.Secp256k1.Internal
      9 import qualified Data.ByteString as BS
     10 import Foreign.Ptr (Ptr)
     11 import qualified Foreign.Ptr as F (nullPtr, castPtr)
     12 import qualified Foreign.Marshal.Alloc as A (alloca, allocaBytes)
     13 import qualified Foreign.Storable as S (poke, peek)
     14 import qualified System.Entropy as E
     15 import Test.Tasty
     16 import Test.Tasty.HUnit
     17 
     18 data Secp256k1Error = Secp256k1Error
     19   deriving Show
     20 
     21 instance Exception Secp256k1Error
     22 
     23 main :: IO ()
     24 main = defaultMain units
     25 
     26 units :: TestTree
     27 units = testGroup "unit tests" [
     28     context_create
     29   , context_randomize
     30   , ec_pubkey_parse
     31   , ec_pubkey_serialize_compressed
     32   , ec_pubkey_serialize_uncompressed
     33   , ec_pubkey_create
     34   , ec_pubkey_tweak_add
     35   , ec_pubkey_tweak_mul
     36   , ec_seckey_tweak_add
     37   , ec_seckey_tweak_mul
     38   , ecdsa_signature_parse_der
     39   , ecdsa_signature_serialize_der
     40   , ecdsa_signature_compact
     41   , ecdsa_sign
     42   , ecdsa_verify_compressed
     43   , ecdsa_verify_uncompressed
     44   , ecdh_test
     45   , xonly_pubkey_serialize_test
     46   , xonly_pubkey_parse_test
     47   , keypair_create_test
     48   , schnorr_sign32
     49   , schnorr_verify
     50   ]
     51 
     52 -- context
     53 
     54 wentropy :: (Ptr Seed32 -> IO a) -> IO a
     55 wentropy c = do
     56   bs <- E.getEntropy 32
     57   BS.useAsCString bs $ \(F.castPtr -> b) -> c b
     58 
     59 context_create :: TestTree
     60 context_create = testCase "secp256k1_context_create (non-null)" $
     61   wcontext $ \tex -> assertBool "non-null" $ tex /= F.nullPtr
     62 
     63 context_randomize :: TestTree
     64 context_randomize = testCase "secp256k1_context_randomize (success)" $
     65   wcontext $ \tex -> do
     66     suc <- wentropy (secp256k1_context_randomize tex)
     67     assertBool "success" (suc == 1)
     68 
     69 -- ec
     70 
     71 ec_pubkey_parse :: TestTree
     72 ec_pubkey_parse = testCase "secp256k1_ec_pubkey_parse (success)" $
     73   wcontext $ \tex -> do
     74     -- throws on failure, so any return implies success
     75     _ <- parse_pubkey tex _PUB_COMPRESSED
     76     assertBool "success" True
     77 
     78 ec_pubkey_serialize_compressed :: TestTree
     79 ec_pubkey_serialize_compressed =
     80   testCase "secp256k1_ec_pubkey_serialize (compressed, success)" $
     81     wcontext $ \tex -> do
     82       par <- parse_pubkey tex _PUB_COMPRESSED
     83       pub <- serialize_pubkey_compressed tex par
     84       assertEqual "success" pub _PUB_COMPRESSED
     85 
     86 ec_pubkey_serialize_uncompressed :: TestTree
     87 ec_pubkey_serialize_uncompressed =
     88   testCase "secp256k1_ec_pubkey_serialize (uncompressed, success)" $
     89     wcontext $ \tex -> do
     90       par <- parse_pubkey tex _PUB_UNCOMPRESSED
     91       pub <- serialize_pubkey_uncompressed tex par
     92       assertEqual "success" pub _PUB_UNCOMPRESSED
     93 
     94 ec_pubkey_create :: TestTree
     95 ec_pubkey_create =
     96   testCase "secp256k1_ec_pubkey_create (success)" $
     97     wcontext $ \tex -> do
     98       _ <- create_pubkey tex _SEC
     99       assertBool "success" True
    100 
    101 ec_pubkey_tweak_add :: TestTree
    102 ec_pubkey_tweak_add =
    103   testCase "secp256k1_ec_pubkey_tweak_add (success)" $
    104     wcontext $ \tex -> do
    105       pub <- parse_pubkey tex _PUB_COMPRESSED
    106       add <- tweak_pub_add tex pub _TWEAK
    107       eek <- serialize_pubkey_uncompressed tex add
    108       assertEqual "success" eek _PUB_ADD_TWEAKED
    109 
    110 ec_pubkey_tweak_mul :: TestTree
    111 ec_pubkey_tweak_mul =
    112   testCase "secp256k1_ec_pubkey_tweak_mul (success)" $
    113     wcontext $ \tex -> do
    114       pub <- parse_pubkey tex _PUB_COMPRESSED
    115       mul <- tweak_pub_mul tex pub _TWEAK
    116       eek <- serialize_pubkey_uncompressed tex mul
    117       assertEqual "success" eek _PUB_MUL_TWEAKED
    118 
    119 ec_seckey_tweak_add :: TestTree
    120 ec_seckey_tweak_add =
    121   testCase "secp256k1_ec_seckey_tweak_add (success)" $
    122     wcontext $ \tex -> do
    123       eek <- tweak_sec_add tex _SEC _TWEAK
    124       assertEqual "success" eek _SEC_ADD_TWEAKED
    125 
    126 ec_seckey_tweak_mul :: TestTree
    127 ec_seckey_tweak_mul =
    128   testCase "secp256k1_ec_seckey_tweak_mul (success)" $
    129     wcontext $ \tex -> do
    130       eek <- tweak_sec_mul tex _SEC _TWEAK
    131       assertEqual "success" eek _SEC_MUL_TWEAKED
    132 
    133 -- ecdsa
    134 
    135 ecdsa_signature_parse_der :: TestTree
    136 ecdsa_signature_parse_der =
    137   testCase "secp256k1_ecdsa_signature_parse_der (success)" $
    138     wcontext $ \tex -> do
    139       -- throws on failure, so any return implies success
    140       _ <- parse_der tex _DER
    141       assertBool "success" True
    142 
    143 ecdsa_signature_serialize_der :: TestTree
    144 ecdsa_signature_serialize_der =
    145   testCase "secp256k1_ecdsa_signature_serialize_der (success)" $
    146     wcontext $ \tex -> do
    147       par <- parse_der tex _DER
    148       der <- serialize_der tex par
    149       assertEqual "success" der _DER
    150 
    151 -- joint parse, serialize test
    152 ecdsa_signature_compact :: TestTree
    153 ecdsa_signature_compact =
    154   testCase "secp256k1_ecdsa_signature_{parse, serialize}_compact (success)" $
    155     wcontext $ \tex -> do
    156       sig <- parse_der tex _DER
    157       com <- serialize_compact tex sig
    158       par <- parse_compact tex com
    159       der <- serialize_der tex par
    160       assertEqual "success" der _DER
    161 
    162 ecdsa_sign :: TestTree
    163 ecdsa_sign = testCase "secp256k1_ecdsa_sign (success)" $
    164   wcontext $ \tex -> do
    165     par <- parse_der tex _DER
    166     sig <- sign_ecdsa tex _SEC _HAS
    167     assertEqual "success" sig par
    168 
    169 ecdsa_verify_compressed :: TestTree
    170 ecdsa_verify_compressed =
    171   testCase "secp256k1_ecdsa_verify (compressed, success)" $
    172     wcontext $ \tex -> do
    173       suc <- verify_ecdsa tex _PUB_COMPRESSED _HAS _DER
    174       assertBool "success" suc
    175 
    176 ecdsa_verify_uncompressed :: TestTree
    177 ecdsa_verify_uncompressed =
    178   testCase "secp256k1_ecdsa_verify (uncompressed, success)" $
    179     wcontext $ \tex -> do
    180       suc <- verify_ecdsa tex _PUB_UNCOMPRESSED _HAS _DER
    181       assertBool "success" suc
    182 
    183 -- ecdh
    184 
    185 ecdh_test :: TestTree
    186 ecdh_test = testCase "secp256k1_ecdh (success)" $
    187   wcontext $ \tex -> do
    188     -- throws on failure, so any return implies success
    189     _ <- ecdh tex _PUB_COMPRESSED _SEC
    190     assertBool "success" True
    191 
    192 -- extrakeys
    193 
    194 xonly_pubkey_serialize_test :: TestTree
    195 xonly_pubkey_serialize_test =
    196   testCase "secp256k1_xonly_pubkey_serialize (success)" $ do
    197     pux <- wcontext $ \tex -> do
    198       key <- xonly_pubkey_from_pubkey tex _PUB_COMPRESSED
    199       xonly_pubkey_serialize tex key
    200     assertEqual "success" pux _PUB_XONLY
    201 
    202 xonly_pubkey_parse_test :: TestTree
    203 xonly_pubkey_parse_test =
    204   testCase "secp256k1_xonly_pubkey_parse (success)" $ do
    205     wcontext $ \tex -> do
    206       pux <- xonly_pubkey_parse tex _PUB_XONLY
    207       pub <- xonly_pubkey_serialize tex pux
    208       assertEqual "success" pub _PUB_XONLY
    209 
    210 keypair_create_test :: TestTree
    211 keypair_create_test =
    212   testCase "secp256k1_keypair_create (success)" $ do
    213     wcontext $ \tex -> do
    214       per <- keypair_create tex _SEC
    215       sec <- keypair_sec tex per
    216       pub <- keypair_pub tex per
    217       ser <- serialize_pubkey_compressed tex pub
    218       assertEqual "success" sec _SEC
    219       assertEqual "success" ser _PUB_COMPRESSED
    220 
    221 -- schnorr
    222 
    223 schnorr_sign32 :: TestTree
    224 schnorr_sign32 = testCase "secp256k1_schnorrsig_sign32 (success)" $ do
    225   wcontext $ \tex -> do
    226     sig <- schnorrsig_sign32 tex _HAS _SEC
    227     assertEqual "success" sig _SIG_SCHNORR
    228 
    229 schnorr_verify :: TestTree
    230 schnorr_verify = testCase "secp256k1_schnorrsig_verify (success)" $ do
    231   wcontext $ \tex -> do
    232     suc <- schnorrsig_verify tex _SIG_SCHNORR _HAS _PUB_COMPRESSED
    233     assertBool "success" suc
    234 
    235 -- wrappers
    236 
    237 parse_der :: Ptr Context -> BS.ByteString -> IO BS.ByteString
    238 parse_der tex bs =
    239   BS.useAsCStringLen bs $ \(F.castPtr -> der, fromIntegral -> len) ->
    240     A.allocaBytes _SIG_BYTES $ \out -> do
    241       suc <- secp256k1_ecdsa_signature_parse_der tex out der len
    242       when (suc /= 1) $ throwIO Secp256k1Error
    243       let par = F.castPtr out
    244       BS.packCStringLen (par, _SIG_BYTES)
    245 
    246 serialize_der :: Ptr Context -> BS.ByteString -> IO BS.ByteString
    247 serialize_der tex bs = A.alloca $ \len ->
    248   A.allocaBytes _DER_BYTES $ \out ->
    249     BS.useAsCString bs $ \(F.castPtr -> sig) -> do
    250       let siz = fromIntegral _DER_BYTES
    251       S.poke len siz
    252       suc <- secp256k1_ecdsa_signature_serialize_der tex out len sig
    253       when (suc /= 1) $ throwIO Secp256k1Error
    254       pek <- S.peek len
    255       let enc = F.castPtr out
    256           nel = fromIntegral pek
    257       BS.packCStringLen (enc, nel)
    258 
    259 parse_compact :: Ptr Context -> BS.ByteString -> IO BS.ByteString
    260 parse_compact tex bs =
    261   BS.useAsCString bs $ \(F.castPtr -> com) ->
    262     A.allocaBytes _SIG_BYTES $ \out -> do
    263       suc <- secp256k1_ecdsa_signature_parse_compact tex out com
    264       when (suc /= 1) $ throwIO Secp256k1Error
    265       let par = F.castPtr out
    266       BS.packCStringLen (par, _SIG_BYTES)
    267 
    268 serialize_compact :: Ptr Context -> BS.ByteString -> IO BS.ByteString
    269 serialize_compact tex bs =
    270   BS.useAsCString bs $ \(F.castPtr -> sig) ->
    271     A.allocaBytes _SIG_BYTES $ \out -> do
    272       -- always returns 1
    273       _ <- secp256k1_ecdsa_signature_serialize_compact tex out sig
    274       let enc = F.castPtr out
    275       BS.packCStringLen (enc, _SIG_BYTES)
    276 
    277 parse_pubkey :: Ptr Context -> BS.ByteString -> IO BS.ByteString
    278 parse_pubkey tex bs =
    279   BS.useAsCStringLen bs $ \(F.castPtr -> pub, fromIntegral -> len) ->
    280     A.allocaBytes _PUB_BYTES_INTERNAL $ \out -> do
    281       suc <- secp256k1_ec_pubkey_parse tex out pub len
    282       when (suc /= 1) $ throwIO Secp256k1Error
    283       let par = F.castPtr out
    284       BS.packCStringLen (par, _PUB_BYTES_INTERNAL)
    285 
    286 create_pubkey :: Ptr Context -> BS.ByteString -> IO BS.ByteString
    287 create_pubkey tex bs =
    288   BS.useAsCString bs $ \(F.castPtr -> sec) ->
    289     A.allocaBytes _PUB_BYTES_INTERNAL $ \out -> do
    290       suc <- secp256k1_ec_pubkey_create tex out sec
    291       when (suc /= 1) $ throwIO Secp256k1Error
    292       let pub = F.castPtr out
    293       BS.packCStringLen (pub, _PUB_BYTES_INTERNAL)
    294 
    295 serialize_pubkey_compressed :: Ptr Context -> BS.ByteString -> IO BS.ByteString
    296 serialize_pubkey_compressed tex bs =
    297   BS.useAsCString bs $ \(F.castPtr -> pub) ->
    298     A.alloca $ \len ->
    299       A.allocaBytes _PUB_BYTES_COMPRESSED $ \out -> do
    300         let siz = fromIntegral _PUB_BYTES_COMPRESSED
    301         S.poke len siz
    302         suc <- secp256k1_ec_pubkey_serialize tex out len pub _COMPRESSED_FLAG
    303         when (suc /= 1) $ throwIO Secp256k1Error
    304         pec <- S.peek len
    305         let enc = F.castPtr out
    306             nel = fromIntegral pec
    307         BS.packCStringLen (enc, nel)
    308 
    309 serialize_pubkey_uncompressed
    310   :: Ptr Context
    311   -> BS.ByteString
    312   -> IO BS.ByteString
    313 serialize_pubkey_uncompressed tex bs =
    314   BS.useAsCString bs $ \(F.castPtr -> pub) ->
    315     A.alloca $ \len ->
    316       A.allocaBytes _PUB_BYTES_UNCOMPRESSED $ \out -> do
    317         let siz = fromIntegral _PUB_BYTES_UNCOMPRESSED
    318         S.poke len siz
    319         suc <- secp256k1_ec_pubkey_serialize tex out len pub _UNCOMPRESSED_FLAG
    320         when (suc /= 1) $ throwIO Secp256k1Error
    321         pec <- S.peek len
    322         let enc = F.castPtr out
    323             nel = fromIntegral pec
    324         BS.packCStringLen (enc, nel)
    325 
    326 tweak_pub_add
    327   :: Ptr Context
    328   -> BS.ByteString
    329   -> BS.ByteString
    330   -> IO BS.ByteString
    331 tweak_pub_add tex (BS.copy -> pub) wee =
    332   BS.useAsCString pub $ \(F.castPtr -> out) ->
    333     BS.useAsCString wee $ \(F.castPtr -> eek) -> do
    334       suc <- secp256k1_ec_pubkey_tweak_add tex out eek
    335       when (suc /= 1) $ throwIO Secp256k1Error
    336       let enc = F.castPtr out
    337       BS.packCStringLen (enc, _PUB_BYTES_INTERNAL)
    338 
    339 tweak_pub_mul
    340   :: Ptr Context
    341   -> BS.ByteString
    342   -> BS.ByteString
    343   -> IO BS.ByteString
    344 tweak_pub_mul tex (BS.copy -> pub) wee =
    345   BS.useAsCString pub $ \(F.castPtr -> out) ->
    346     BS.useAsCString wee $ \(F.castPtr -> eek) -> do
    347       suc <- secp256k1_ec_pubkey_tweak_mul tex out eek
    348       when (suc /= 1) $ throwIO Secp256k1Error
    349       let enc = F.castPtr out
    350       BS.packCStringLen (enc, _PUB_BYTES_INTERNAL)
    351 
    352 tweak_sec_add
    353   :: Ptr Context
    354   -> BS.ByteString
    355   -> BS.ByteString
    356   -> IO BS.ByteString
    357 tweak_sec_add tex (BS.copy -> sec) wee =
    358   BS.useAsCString sec $ \(F.castPtr -> out) ->
    359     BS.useAsCString wee $ \(F.castPtr -> eek) -> do
    360       suc <- secp256k1_ec_seckey_tweak_add tex out eek
    361       when (suc /= 1) $ throwIO Secp256k1Error
    362       let enc = F.castPtr out
    363       BS.packCStringLen (enc, _SEC_BYTES)
    364 
    365 tweak_sec_mul
    366   :: Ptr Context
    367   -> BS.ByteString
    368   -> BS.ByteString
    369   -> IO BS.ByteString
    370 tweak_sec_mul tex (BS.copy -> sec) wee =
    371   BS.useAsCString sec $ \(F.castPtr -> out) ->
    372     BS.useAsCString wee $ \(F.castPtr -> eek) -> do
    373       suc <- secp256k1_ec_seckey_tweak_mul tex out eek
    374       when (suc /= 1) $ throwIO Secp256k1Error
    375       let enc = F.castPtr out
    376       BS.packCStringLen (enc, _SEC_BYTES)
    377 
    378 sign_ecdsa :: Ptr Context -> BS.ByteString -> BS.ByteString -> IO BS.ByteString
    379 sign_ecdsa tex key msg =
    380   A.allocaBytes _SIG_BYTES $ \out ->
    381     BS.useAsCString msg $ \(F.castPtr -> has) ->
    382       BS.useAsCString key $ \(F.castPtr -> sec) -> do
    383         suc <- secp256k1_ecdsa_sign tex out has sec F.nullPtr F.nullPtr
    384         when (suc /= 1) $ throwIO Secp256k1Error
    385         let sig = F.castPtr out
    386         BS.packCStringLen (sig, _SIG_BYTES)
    387 
    388 verify_ecdsa
    389   :: Ptr Context
    390   -> BS.ByteString
    391   -> BS.ByteString
    392   -> BS.ByteString
    393   -> IO Bool
    394 verify_ecdsa tex key msg der = do
    395   sig <- parse_der tex der
    396   pub <- parse_pubkey tex key
    397   suc <- BS.useAsCString msg $ \(F.castPtr -> has) ->
    398     BS.useAsCString pub $ \(F.castPtr -> kep) ->
    399       BS.useAsCString sig $ \(F.castPtr -> sip) ->
    400         secp256k1_ecdsa_verify tex sip has kep
    401   pure (suc == 1)
    402 
    403 ecdh :: Ptr Context -> BS.ByteString -> BS.ByteString -> IO BS.ByteString
    404 ecdh tex pub sec =
    405   A.allocaBytes _SEC_BYTES $ \out -> do
    406     par <- parse_pubkey tex pub
    407     BS.useAsCString par $ \(F.castPtr -> pab) ->
    408       BS.useAsCString sec $ \(F.castPtr -> sep) -> do
    409         suc <- secp256k1_ecdh tex out pab sep F.nullPtr F.nullPtr
    410         when (suc /= 1) $ throwIO Secp256k1Error
    411         let key = F.castPtr out
    412         BS.packCStringLen (key, _SEC_BYTES)
    413 
    414 xonly_pubkey_from_pubkey :: Ptr Context -> BS.ByteString -> IO BS.ByteString
    415 xonly_pubkey_from_pubkey tex pub =
    416   A.allocaBytes _PUB_BYTES_INTERNAL $ \out -> do
    417     par <- parse_pubkey tex pub
    418     BS.useAsCString par $ \(F.castPtr -> pab) -> do
    419       -- returns 1 always
    420       _ <- secp256k1_xonly_pubkey_from_pubkey tex out F.nullPtr pab
    421       let key = F.castPtr out
    422       BS.packCStringLen (key, _PUB_BYTES_INTERNAL)
    423 
    424 xonly_pubkey_serialize :: Ptr Context -> BS.ByteString -> IO BS.ByteString
    425 xonly_pubkey_serialize tex pux =
    426   A.allocaBytes _PUB_BYTES_XONLY $ \out -> do
    427     BS.useAsCString pux $ \(F.castPtr -> key) -> do
    428       -- returns 1 always
    429       _ <- secp256k1_xonly_pubkey_serialize tex out key
    430       let kep = F.castPtr out
    431       BS.packCStringLen (kep, _PUB_BYTES_XONLY)
    432 
    433 xonly_pubkey_parse :: Ptr Context -> BS.ByteString -> IO BS.ByteString
    434 xonly_pubkey_parse tex pub =
    435   A.allocaBytes _PUB_BYTES_INTERNAL $ \out ->
    436     BS.useAsCString pub $ \(F.castPtr -> pux) -> do
    437       suc <- secp256k1_xonly_pubkey_parse tex out pux
    438       when (suc /= 1) $ throwIO Secp256k1Error
    439       let key = F.castPtr out
    440       BS.packCStringLen (key, _PUB_BYTES_INTERNAL)
    441 
    442 keypair_create :: Ptr Context -> BS.ByteString -> IO BS.ByteString
    443 keypair_create tex sec =
    444   A.allocaBytes _KEYPAIR_BYTES $ \out ->
    445     BS.useAsCString sec $ \(F.castPtr -> key) -> do
    446       suc <- secp256k1_keypair_create tex out key
    447       when (suc /= 1) $ throwIO Secp256k1Error
    448       let per = F.castPtr out
    449       BS.packCStringLen (per, _KEYPAIR_BYTES)
    450 
    451 keypair_pub :: Ptr Context -> BS.ByteString -> IO BS.ByteString
    452 keypair_pub tex per =
    453   A.allocaBytes _PUB_BYTES_INTERNAL $ \out ->
    454     BS.useAsCString per $ \(F.castPtr -> par) -> do
    455       _ <- secp256k1_keypair_pub tex out par
    456       let enc = F.castPtr out
    457       BS.packCStringLen (enc, _PUB_BYTES_INTERNAL)
    458 
    459 keypair_sec :: Ptr Context -> BS.ByteString -> IO BS.ByteString
    460 keypair_sec tex per =
    461   A.allocaBytes _SEC_BYTES $ \out ->
    462     BS.useAsCString per $ \(F.castPtr -> par) -> do
    463       _ <- secp256k1_keypair_sec tex out par
    464       let enc = F.castPtr out
    465       BS.packCStringLen (enc, _SEC_BYTES)
    466 
    467 schnorrsig_sign32
    468   :: Ptr Context
    469   -> BS.ByteString
    470   -> BS.ByteString
    471   -> IO BS.ByteString
    472 schnorrsig_sign32 tex msg sec =
    473   A.allocaBytes _SIG_BYTES $ \out ->
    474     BS.useAsCString msg $ \(F.castPtr -> has) -> do
    475       per <- keypair_create tex sec
    476       BS.useAsCString per $ \(F.castPtr -> pur) -> do
    477         suc <- secp256k1_schnorrsig_sign32 tex out has pur F.nullPtr
    478         when (suc /= 1) $ throwIO Secp256k1Error
    479         let enc = F.castPtr out
    480         BS.packCStringLen (enc, _SIG_BYTES)
    481 
    482 schnorrsig_verify
    483   :: Ptr Context
    484   -> BS.ByteString
    485   -> BS.ByteString
    486   -> BS.ByteString
    487   -> IO Bool
    488 schnorrsig_verify tex sig msg pub =
    489   BS.useAsCString sig $ \(F.castPtr -> sip) ->
    490     BS.useAsCStringLen msg $ \(F.castPtr -> has, fromIntegral -> len) -> do
    491       pux <- xonly_pubkey_from_pubkey tex pub
    492       BS.useAsCString pux $ \(F.castPtr -> pax) -> do
    493         suc <- secp256k1_schnorrsig_verify tex sip has len pax
    494         pure (suc == 1)
    495 
    496 -- test inputs
    497 
    498 -- mostly grabbed from haskoin/secp256k1-haskell
    499 
    500 -- DER-encoded signature
    501 _DER :: BS.ByteString
    502 _DER = mconcat [
    503     "0E\STX!\NUL\245\STX\191\160z\244>~\242ea\139\r\146\154v\EM\238\SOH\214"
    504   , "\NAK\SO7\235n\170\242\200\189\&7\251\"\STX o\EOT\NAK\171\SO\154\151z"
    505   , "\253x\178\194n\243\155\&9R\tm1\159\212\177\SOH\199h\173l\DC3.0E"
    506   ]
    507 
    508 -- a 32-byte message hash
    509 _HAS :: BS.ByteString
    510 _HAS = mconcat [
    511     "\245\203\231\216\129\130\164\184\228\NUL\249k\ACK\DC2\137!\134J"
    512   , "\CAN\CAN}\DC1L\138\232T\ESCVl\138\206\NUL"
    513   ]
    514 
    515 -- a 32-byte secret key
    516 _SEC :: BS.ByteString
    517 _SEC = mconcat [
    518     "\246RU\tMws\237\141\212\ETB\186\220\159\192E\193\248\SI\220[-%\ETB"
    519   , "+\ETX\FS\230\147>\ETX\154"
    520   ]
    521 
    522 -- 32-bytes
    523 _TWEAK :: BS.ByteString
    524 _TWEAK = mconcat [
    525     "\245\203\231\216\129\130\164\184\228\NUL\249k\ACK\DC2\137!\134J"
    526   , "\CAN\CAN}\DC1L\138\232T\ESCVl\138\206\NUL"
    527   ]
    528 
    529 -- _PUB add-tweaked with _TWEAK
    530 _PUB_ADD_TWEAKED :: BS.ByteString
    531 _PUB_ADD_TWEAKED = mconcat [
    532     "\EOTD\FS9\130\185uvdn\r\240\201g6\ACK=\246\180/.\229f\209;\159d$0-"
    533   , "\DC3y\229\CAN\253\200z\DC4\197C[\255z]\180U B\203A \198\184jK\189="
    534   , "\ACKC\243\193J\208\DC3h"
    535   ]
    536 
    537 -- _PUB mul-tweaked with _TWEAK
    538 _PUB_MUL_TWEAKED :: BS.ByteString
    539 _PUB_MUL_TWEAKED = mconcat [
    540     "\EOT\243y\220\153\205\245\200>C=\239\162g\251\179\&7}a\214\183y"
    541   , "\192j\SOL\226\154\227\255SS\177*\228\156\157\a\231\&6\143+\165"
    542   , "\164F\194\ETX%\\\233\DC22)\145\162\214\169\213\213v\FSa\237\CANE"
    543   ]
    544 
    545 -- _SEC add-tweaked with _TWEAK
    546 _SEC_ADD_TWEAKED :: BS.ByteString
    547 _SEC_ADD_TWEAKED = mconcat [
    548     "\236\RS<\225\206\250\CAN\166q\213\DC1%\226\178Ih\141\147K\SO(\245"
    549   , "\209fS\132\217\176/\146\144Y"
    550   ]
    551 
    552 -- _SEC mul-tweaked with _TWEAK
    553 _SEC_MUL_TWEAKED :: BS.ByteString
    554 _SEC_MUL_TWEAKED = mconcat [
    555     "\169oYbI:\203\ETB\159`\168j\151\133\252z0\224\195\155d\192\157$\254"
    556   , "\ACKM\154\239\NAK\228\192"
    557   ]
    558 
    559 -- 33-byte (compressed) public key
    560 _PUB_COMPRESSED :: BS.ByteString
    561 _PUB_COMPRESSED = mconcat [
    562     "\ETX\221\237B\ETX\218\201j~\133\242\195t\163|\227\233\201\161U"
    563   , "\167+d\180U\ESC\v\254w\157\212G\ENQ"
    564   ]
    565 
    566 -- 65-byte (uncompressed) public key
    567 _PUB_UNCOMPRESSED :: BS.ByteString
    568 _PUB_UNCOMPRESSED = mconcat [
    569     "\EOT\221\237B\ETX\218\201j~\133\242\195t\163|\227\233\201\161U\167"
    570   , "+d\180U\ESC\v\254w\157\212G\ENQ\DC2!=^\215\144R,\EOT-\238\142\133"
    571   , "\196\192\236_\150\128\vr\188Y@\200\188\FS^\DC1\228\252\191"
    572   ]
    573 
    574 -- 32-byte x-only pubkey
    575 _PUB_XONLY :: BS.ByteString
    576 _PUB_XONLY = mconcat [
    577     "\221\237B\ETX\218\201j~\133\242\195t\163|\227\233\201\161U\167+d"
    578   , "\180U\ESC\v\254w\157\212G\ENQ"
    579   ]
    580 
    581 -- 64-byte schnorr signature
    582 _SIG_SCHNORR :: BS.ByteString
    583 _SIG_SCHNORR  = mconcat [
    584     "\214\185AtJ\189\250Gp\NAK2\221\DC2[\182\209\192j{\140^\222R\NUL~"
    585   , "\139d@<\138\163rh\247\152\r\228\175\236\219\156\151\214~\135\&7"
    586   , "\225\&6\234\220;\164R\191\170\186\243\NAK\147\f\144\156ez"
    587   ]
    588