secp256k1

Pure Haskell Schnorr, ECDSA on the elliptic curve secp256k1 (docs.ppad.tech/secp256k1).
git clone git://git.ppad.tech/secp256k1.git
Log | Files | Refs | README | LICENSE

Weight.hs (5807B)


      1 {-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns #-}
      2 {-# LANGUAGE BangPatterns #-}
      3 {-# LANGUAGE OverloadedStrings #-}
      4 
      5 module Main where
      6 
      7 import qualified Data.ByteString as BS
      8 import qualified Data.ByteString.Base16 as B16
      9 import Data.Maybe (fromJust)
     10 import Data.Word.Wider (Wider(..))
     11 import Control.DeepSeq
     12 import qualified Crypto.Curve.Secp256k1 as S
     13 import qualified Weigh as W
     14 
     15 instance NFData S.Projective
     16 instance NFData S.Affine
     17 instance NFData S.ECDSA
     18 instance NFData S.Context
     19 
     20 decodeLenient :: BS.ByteString -> BS.ByteString
     21 decodeLenient bs = case B16.decode bs of
     22   Nothing -> error "bang"
     23   Just b -> b
     24 
     25 parse_int :: BS.ByteString -> Wider
     26 parse_int bs = case S.parse_int256 bs of
     27   Nothing -> error "bang"
     28   Just v -> v
     29 
     30 -- note that 'weigh' doesn't work properly in a repl
     31 main :: IO ()
     32 main = W.mainWith $ do
     33   parse_int256
     34   ge
     35   add
     36   double
     37   mul
     38   mul_wnaf
     39   derive_pub
     40   schnorr
     41   ecdsa
     42   ecdh
     43 
     44 ge :: W.Weigh ()
     45 ge =
     46   let !t = 2
     47       !b = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed
     48   in  W.wgroup "ge" $ do
     49         W.func' "small" S.ge t
     50         W.func' "large" S.ge b
     51 
     52 parse_int256 :: W.Weigh ()
     53 parse_int256 =
     54   let !a = BS.replicate 32 0x00
     55       !b = BS.replicate 32 0xFF
     56   in  W.wgroup "parse_int256" $ do
     57         W.func' "parse_int (small)" parse_int a
     58         W.func' "parse_int (big)" parse_int b
     59 
     60 add :: W.Weigh ()
     61 add =
     62   let !p = fromJust . S.parse_point . decodeLenient $
     63         "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
     64       !r = fromJust . S.parse_point . decodeLenient $
     65         "03a2113cf152585d96791a42cdd78782757fbfb5c6b2c11b59857eb4f7fda0b0e8"
     66       !q = fromJust . S.parse_point . decodeLenient $
     67         "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9"
     68       !s = fromJust . S.parse_point . decodeLenient $
     69         "0306413898a49c93cccf3db6e9078c1b6a8e62568e4a4770e0d7d96792d1c580ad"
     70   in  W.wgroup "add" $ do
     71         W.func' "p + q (trivial projective points)" (S.add p) q
     72         W.func' "s + p (nontrivial mixed points)" (S.add s) p
     73         W.func' "r + s (nontrivial projective points)" (S.add r) s
     74 
     75 double :: W.Weigh ()
     76 double =
     77   let !p = fromJust . S.parse_point . decodeLenient $
     78         "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
     79       !r = fromJust . S.parse_point . decodeLenient $
     80         "03a2113cf152585d96791a42cdd78782757fbfb5c6b2c11b59857eb4f7fda0b0e8"
     81   in  W.wgroup "double" $ do
     82         W.func' "2 p (double, trivial projective point)" S.double p
     83         W.func' "2 r (double, nontrivial projective point)" S.double r
     84 
     85 mul :: W.Weigh ()
     86 mul =
     87   let !g = S._CURVE_G
     88       !t = 2
     89       !b = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed
     90   in  W.wgroup "mul" $ do
     91         W.func' "2 G" (S.mul g) t
     92         W.func' "(2 ^ 255 - 19) G" (S.mul g) b
     93 
     94 mul_wnaf :: W.Weigh ()
     95 mul_wnaf =
     96   let !t = 2
     97       !b = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed
     98       !con = S.precompute
     99   in  W.wgroup "mul_wnaf" $ do
    100         W.func' "precompute" S._precompute (8 :: Int)
    101         W.func' "2 G" (S.mul_wnaf con) t
    102         W.func' "(2 ^ 255 - 19) G" (S.mul_wnaf con) b
    103 
    104 derive_pub :: W.Weigh ()
    105 derive_pub =
    106   let !t = 2
    107       !b = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed
    108       !con = S.precompute
    109   in  W.wgroup "derive_pub" $ do
    110         W.func' "sk = 2" S.derive_pub t
    111         W.func' "sk = 2 ^ 255 - 19" S.derive_pub b
    112         W.func' "wnaf, sk = 2" (S.derive_pub' con) t
    113         W.func' "wnaf, sk = 2 ^ 255 - 19" (S.derive_pub' con) b
    114 
    115 schnorr :: W.Weigh ()
    116 schnorr =
    117   let !t = 2
    118       !b = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed
    119       !con   = S.precompute
    120       !s_msg = decodeLenient
    121         "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"
    122       !s_aux = decodeLenient
    123         "0000000000000000000000000000000000000000000000000000000000000001"
    124       !s_sig = decodeLenient
    125         "6896BD60EEAE296DB48A229FF71DFE071BDE413E6D43F917DC8DCF8C78DE33418906D11AC976ABCCB20B091292BFF4EA897EFCB639EA871CFA95F6DE339E4B0A"
    126       !(Just !s_pk) = S.parse_point . decodeLenient $
    127         "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"
    128   in  W.wgroup "schnorr" $ do
    129         W.func "sign_schnorr (small)" (S.sign_schnorr t s_msg) s_aux
    130         W.func "sign_schnorr (large)" (S.sign_schnorr b s_msg) s_aux
    131         W.func "sign_schnorr' (small)" (S.sign_schnorr' con t s_msg) s_aux
    132         W.func "sign_schnorr' (large)" (S.sign_schnorr' con b s_msg) s_aux
    133         W.func "verify_schnorr" (S.verify_schnorr s_msg s_pk) s_sig
    134         W.func "verify_schnorr'" (S.verify_schnorr' con s_msg s_pk) s_sig
    135 
    136 ecdsa :: W.Weigh ()
    137 ecdsa =
    138   let !t = 2
    139       !b = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed
    140       !con   = S.precompute
    141       !msg   = "i approve of this message"
    142       !s_msg = decodeLenient
    143         "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"
    144       !(Just !pub) = S.derive_pub b
    145       !(Just !sig) = S.sign_ecdsa b s_msg
    146   in   W.wgroup "ecdsa" $ do
    147          W.func "sign_ecdsa (small)" (S.sign_ecdsa t) s_msg
    148          W.func "sign_ecdsa (large)" (S.sign_ecdsa b) s_msg
    149          W.func "sign_ecdsa' (small)" (S.sign_ecdsa' con t) s_msg
    150          W.func "sign_ecdsa' (large)" (S.sign_ecdsa' con b) s_msg
    151          W.func "verify_ecdsa" (S.verify_ecdsa msg pub) sig
    152          W.func "verify_ecdsa'" (S.verify_ecdsa' con msg pub) sig
    153 
    154 ecdh :: W.Weigh ()
    155 ecdh =
    156   let !b = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed
    157       !(Just !pub) = S.parse_point . decodeLenient $
    158         "bd02b9dfc8ef760708950bd972f2dc244893b61b6b46c3b19be1b2da7b034ac5"
    159   in  W.wgroup "ecdh" $ do
    160         W.func "ecdh (small)" (S.ecdh pub) 2
    161         W.func "ecdh (large)" (S.ecdh pub) b
    162