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 9603f1e4a327c3007df36f7afdc16954eefcf314
parent edf681f4a679a52118d0c750572e3efb5b9439f3
Author: Jared Tobin <jared@jtobin.io>
Date:   Mon, 25 Nov 2024 15:40:04 +0400

lib: add wnaf-powered derive_pub

Diffstat:
Mbench/Main.hs | 11++++++++---
Mlib/Crypto/Curve/Secp256k1.hs | 17+++++++++++++++++
Mtest/Main.hs | 2--
3 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/bench/Main.hs b/bench/Main.hs @@ -92,14 +92,19 @@ mul_wnaf = env setup $ \ ~(tex, x) -> pure (tex, int) derive_pub :: Benchmark -derive_pub = env setup $ \x -> +derive_pub = env setup $ \ ~(tex, x) -> bgroup "derive_pub" [ bench "sk = 2" $ nf S.derive_pub 2 , bench "sk = 2 ^ 255 - 19" $ nf S.derive_pub x + , bench "wnaf, sk = 2" $ nf (S.derive_pub' tex) 2 + , bench "wnaf, sk = 2 ^ 255 - 19" $ nf (S.derive_pub' tex) x ] where - setup = pure . S.parse_int256 $ B16.decodeLenient - "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed" + setup = do + let !tex = S.precompute + !int = S.parse_int256 $ B16.decodeLenient + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed" + pure (tex, int) schnorr :: Benchmark schnorr = env setup $ \ ~(tex, big) -> diff --git a/lib/Crypto/Curve/Secp256k1.hs b/lib/Crypto/Curve/Secp256k1.hs @@ -24,6 +24,7 @@ module Crypto.Curve.Secp256k1 ( -- * secp256k1 points Pub , derive_pub + , derive_pub' -- * Parsing , parse_int256 @@ -680,6 +681,22 @@ derive_pub _SECRET mul _CURVE_G _SECRET {-# NOINLINE derive_pub #-} +-- | The same as 'derive_pub', except uses a 'Context' to optimise +-- internal calculations. +-- +-- >>> import qualified System.Entropy as E +-- >>> sk <- fmap parse_int256 (E.getEntropy 32) +-- >>> let !tex = precompute +-- >>> derive_pub' tex sk +-- "<secp256k1 point>" +derive_pub' :: Context -> Integer -> Pub +derive_pub' tex _SECRET + | not (ge _SECRET) = + error "ppad-secp256k1 (derive_pub): invalid secret key" + | otherwise = + mul_wnaf tex _SECRET +{-# NOINLINE derive_pub' #-} + -- parsing -------------------------------------------------------------------- -- | Parse a positive 256-bit 'Integer', /e.g./ a Schnorr or ECDSA diff --git a/test/Main.hs b/test/Main.hs @@ -69,7 +69,6 @@ parse_point_tests = testGroup "parse_point tests" [ render :: Show a => a -> String render = filter (`notElem` ("\"" :: String)) . show --- XX replace these with something non-stupid parse_point_test_p :: TestTree parse_point_test_p = testCase (render p_hex) $ case parse_point (B16.decodeLenient p_hex) of @@ -88,7 +87,6 @@ parse_point_test_r = testCase (render r_hex) $ Nothing -> assertFailure "bad parse" Just r -> assertEqual mempty r_pro r --- XX also make less dumb add_tests :: TestTree add_tests = testGroup "ec addition" [ add_test_pq