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

commit f0fd1290bbc87259ce8bfd930d59bcbdc1cb4539
parent f65d51f02449637aca9afd427a3969f7c8d0b006
Author: Jared Tobin <jared@jtobin.io>
Date:   Wed, 16 Oct 2024 23:18:58 +0400

bench: flesh out

Diffstat:
Mbench/Main.hs | 181++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 114 insertions(+), 67 deletions(-)

diff --git a/bench/Main.hs b/bench/Main.hs @@ -1,8 +1,10 @@ +{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE OverloadedStrings #-} module Main where +import qualified Data.ByteString as BS import qualified Data.ByteString.Base16 as B16 import Control.DeepSeq import Criterion.Main @@ -10,76 +12,121 @@ import qualified Crypto.Curve.Secp256k1 as S instance NFData S.Projective instance NFData S.Affine +instance NFData S.ECDSA main :: IO () main = defaultMain [ - secp256k1 + parse_point + , add + , mul + , schnorr + , ecdsa ] --- to benchmark --- --- parse_point --- parse_integer --- --- add_proj, add_mixed, double --- mul, neg --- --- schnorr sign/verify --- ecdsa sign/verify - -secp256k1 :: Benchmark -secp256k1 = env setup $ \ ~(p_raw, p, q, r, s) -> - bgroup "secp256k1" [ - bgroup "parse_point" [ - bench "p" $ nf S.parse_point p_raw - ] - -- , bgroup "add" [ - -- bench "2 p (double, trivial projective point)" $ nf (S.add p) p - -- , bench "p + q (trivial projective points)" $ nf (S.add p) q - -- , bench "2 r (double, nontrivial projective point)" $ nf (S.add r) r - -- , bench "p + s (nontrivial mixed points)" $ nf (S.add p) s - -- , bench "s + r (nontrivial projective points)" $ nf (S.add s) r - -- ] - -- , bgroup "mul" [ - -- bench "3 p (trivial projective point)" $ nf (S.mul p) 3 - -- , bench "3 r (nontrivial projective point)" $ nf (S.mul r) 3 - -- , bench "<large group element> p" $ - -- nf (S.mul p) (S._CURVE_Q - 0xFFFFFFFFFFFFFFFFFFFFFFFF) - -- ] - ] - where - setup = do - let p_raw = B16.decodeLenient - "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" - q_raw = B16.decodeLenient - "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9" - r_raw = B16.decodeLenient - "03a2113cf152585d96791a42cdd78782757fbfb5c6b2c11b59857eb4f7fda0b0e8" - s_raw = B16.decodeLenient - "0306413898a49c93cccf3db6e9078c1b6a8e62568e4a4770e0d7d96792d1c580ad" - -- all points w/proj_z = 1 - p = case S.parse_point p_raw of - Nothing -> error "bang" - Just !pt -> pt - q = case S.parse_point q_raw of - Nothing -> error "bang" - Just !pt -> pt - r = case S.parse_point r_raw of - Nothing -> error "bang" - Just !pt -> pt - s = case S.parse_point s_raw of - Nothing -> error "bang" - Just !pt -> pt - -- p + q, r + s are nontrivial projective points - pure (p_raw, p, q, S.add p q, S.add r s) - - -- baz :: S.Projective - -- baz = case S.parse_point (B16.decodeLenient r) of - -- Nothing -> error "bang" - -- Just !pa -> pa - - -- qux :: S.Projective - -- qux = case S.parse_point s of - -- Nothing -> error "bang" - -- Just !pa -> pa +parse_point :: Benchmark +parse_point = bgroup "parse_point" [ + bench "compressed" $ nf S.parse_point p_bs + , bench "uncompressed" $ nf S.parse_point t_bs + , bench "bip0340" $ nf S.parse_point (BS.drop 1 p_bs) + ] + +add :: Benchmark +add = bgroup "add" [ + bench "2 p (double, trivial projective point)" $ nf (S.add p) p + , bench "2 r (double, nontrivial projective point)" $ nf (S.add r) r + , bench "p + q (trivial projective points)" $ nf (S.add p) q + , bench "p + s (nontrivial mixed points)" $ nf (S.add p) s + , bench "s + r (nontrivial projective points)" $ nf (S.add s) r + ] + +mul :: Benchmark +mul = bgroup "mul" [ + bench "3 p (trivial projective point)" $ nf (S.mul p) 3 + , bench "3 r (nontrivial projective point)" $ nf (S.mul r) 3 + , bench "<large group element> p" $ + nf (S.mul p) (S._CURVE_Q - 0xFFFFFFFFFFFFFFFFFFFFFFFF) + ] + +schnorr :: Benchmark +schnorr = bgroup "schnorr" [ + bench "sign_schnorr" $ nf (S.sign_schnorr s_sk s_msg) s_aux + , bench "verify_schnorr" $ nf (S.verify_schnorr s_msg s_pk) s_sig + ] + +ecdsa :: Benchmark +ecdsa = bgroup "ecdsa" [ + bench "sign_ecdsa" $ nf (S.sign_ecdsa s_sk) s_msg + -- , bench "verify_ecdsa" $ nf (S.verify_ecdsa e_msg t) e_sig + ] + +p_bs :: BS.ByteString +p_bs = B16.decodeLenient + "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" + +p :: S.Projective +p = case S.parse_point p_bs of + Nothing -> error "bang" + Just !pt -> pt + +q_bs :: BS.ByteString +q_bs = B16.decodeLenient + "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9" + +q :: S.Projective +q = case S.parse_point q_bs of + Nothing -> error "bang" + Just !pt -> pt + +r_bs :: BS.ByteString +r_bs = B16.decodeLenient + "03a2113cf152585d96791a42cdd78782757fbfb5c6b2c11b59857eb4f7fda0b0e8" + +r :: S.Projective +r = case S.parse_point r_bs of + Nothing -> error "bang" + Just !pt -> pt + +s_bs :: BS.ByteString +s_bs = B16.decodeLenient + "0306413898a49c93cccf3db6e9078c1b6a8e62568e4a4770e0d7d96792d1c580ad" + +s :: S.Projective +s = case S.parse_point s_bs of + Nothing -> error "bang" + Just !pt -> pt + +t_bs :: BS.ByteString +t_bs = B16.decodeLenient "04b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6ff0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9" + +t :: S.Projective +t = case S.parse_point t_bs of + Nothing -> error "bang" + Just !pt -> pt + +s_sk :: Integer +s_sk = S.parse_integer . B16.decodeLenient $ + "B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF" + +s_sig :: BS.ByteString +s_sig = B16.decodeLenient "6896BD60EEAE296DB48A229FF71DFE071BDE413E6D43F917DC8DCF8C78DE33418906D11AC976ABCCB20B091292BFF4EA897EFCB639EA871CFA95F6DE339E4B0A" + +s_pk_raw :: BS.ByteString +s_pk_raw = B16.decodeLenient + "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659" + +s_pk :: S.Projective +s_pk = case S.parse_point s_pk_raw of + Nothing -> error "bang" + Just !pt -> pt + +s_msg :: BS.ByteString +s_msg = B16.decodeLenient + "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89" + +s_aux :: BS.ByteString +s_aux = B16.decodeLenient + "0000000000000000000000000000000000000000000000000000000000000001" + +-- e_msg = B16.decodeLenient "313233343030" +-- e_sig = B16.decodeLenient "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba"