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 eeaf72c0918819765b95148b140a6117dd612e9c
parent 2d95f50b098af1b5ca1fa321eed86b0e7c7780b5
Author: Jared Tobin <jared@jtobin.io>
Date:   Sun, 16 Feb 2025 16:34:22 +0400

lib: export _CURVE_ZERO

Diffstat:
Mlib/Crypto/Curve/Secp256k1.hs | 49++++++++++++++++++++++++++++---------------------
1 file changed, 28 insertions(+), 21 deletions(-)

diff --git a/lib/Crypto/Curve/Secp256k1.hs b/lib/Crypto/Curve/Secp256k1.hs @@ -21,10 +21,18 @@ -- "low-S" signatures) on the elliptic curve secp256k1. module Crypto.Curve.Secp256k1 ( + -- * Field and group parameters + _CURVE_Q + , _CURVE_P + , remQ + , modQ + -- * secp256k1 points - Pub + , Pub , derive_pub , derive_pub' + , _CURVE_G + , _CURVE_ZERO -- * Parsing , parse_int256 @@ -74,11 +82,6 @@ module Crypto.Curve.Secp256k1 ( -- for testing/benchmarking , _sign_ecdsa_no_hash , _sign_ecdsa_no_hash' - , _CURVE_P - , _CURVE_Q - , _CURVE_G - , remQ - , modQ ) where import Control.Monad (when) @@ -228,7 +231,7 @@ type Pub = Projective -- Convert to affine coordinates. affine :: Projective -> Affine affine p@(Projective x y z) - | p == _ZERO = Affine 0 0 + | p == _CURVE_ZERO = Affine 0 0 | z == 1 = Affine x y | otherwise = case modinv z (fi _CURVE_P) of Nothing -> error "ppad-secp256k1 (affine): impossible point" @@ -237,7 +240,7 @@ affine p@(Projective x y z) -- Convert to projective coordinates. projective :: Affine -> Projective projective (Affine x y) - | x == 0 && y == 0 = _ZERO + | x == 0 && y == 0 = _CURVE_ZERO | otherwise = Projective x y 1 -- Point is valid @@ -251,13 +254,13 @@ valid p = case affine p of -- curve parameters ----------------------------------------------------------- -- see https://www.secg.org/sec2-v2.pdf for parameter specs --- secp256k1 field prime +-- | secp256k1 field prime. -- --- = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1 +-- = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1 _CURVE_P :: Integer _CURVE_P = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F --- secp256k1 group order +-- | secp256k1 group order. _CURVE_Q :: Integer _CURVE_Q = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 @@ -281,7 +284,7 @@ _CURVE_A = 0 _CURVE_B :: Integer _CURVE_B = 7 --- secp256k1 generator +-- | secp256k1 generator point. -- -- = parse_point -- "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" @@ -290,9 +293,14 @@ _CURVE_G = Projective x y 1 where x = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 y = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 +-- | secp256k1 zero point / point at infinity / monoidal identity. +_CURVE_ZERO :: Projective +_CURVE_ZERO = Projective 0 1 0 + -- secp256k1 zero point / point at infinity / monoidal identity _ZERO :: Projective _ZERO = Projective 0 1 0 +{-# DEPRECATED _ZERO "use _CURVE_ZERO instead" #-} -- secp256k1 in prime order j-invariant 0 form (i.e. a == 0). weierstrass :: Integer -> Integer @@ -312,13 +320,12 @@ remP :: Integer -> Integer remP a = I.integerRem a _CURVE_P {-# INLINE remP #-} --- Division modulo secp256k1 group order. +-- | Division modulo secp256k1 group order. modQ :: Integer -> Integer modQ a = I.integerMod a _CURVE_Q {-# INLINE modQ #-} --- Division modulo secp256k1 group order, when argument is nonnegative. --- (more efficient than modQ) +-- | Division modulo secp256k1 group order, when argument is nonnegative. remQ :: Integer -> Integer remQ a = I.integerRem a _CURVE_Q {-# INLINE remQ #-} @@ -546,7 +553,7 @@ double (Projective x y z) = runST $ do mul :: Projective -> Integer -> Projective mul p _SECRET | not (ge _SECRET) = error "ppad-secp256k1 (mul): scalar not in group" - | otherwise = loop (0 :: Int) _ZERO _CURVE_G p _SECRET + | otherwise = loop (0 :: Int) _CURVE_ZERO _CURVE_G p _SECRET where loop !j !acc !f !d !m | j == _CURVE_Q_BITS = acc @@ -563,10 +570,10 @@ mul p _SECRET -- Don't use this function if the scalar could potentially be a secret. mul_unsafe :: Projective -> Integer -> Projective mul_unsafe p n - | n == 0 = _ZERO + | n == 0 = _CURVE_ZERO | not (ge n) = error "ppad-secp256k1 (mul_unsafe): scalar not in group" - | otherwise = loop _ZERO p n + | otherwise = loop _CURVE_ZERO p n where loop !r !d m | m <= 0 = r @@ -626,7 +633,7 @@ _precompute ctxW = Context {..} where -- secp256k1 points. mul_wnaf :: Context -> Integer -> Projective mul_wnaf Context {..} _SECRET = - loop 0 _ZERO _CURVE_G _SECRET + loop 0 _CURVE_ZERO _CURVE_G _SECRET where wins = 256 `quot` ctxW + 1 wsize = 2 ^ (ctxW - 1) @@ -915,7 +922,7 @@ _verify_schnorr _mul m (affine -> Affine x_p _) sig (unroll32 r <> unroll32 x_P <> m) dif = add (_mul s) (neg (mul_unsafe (projective capP) e)) - in if dif == _ZERO + in if dif == _CURVE_ZERO then False else let Affine x_R y_R = affine dif in not (I.integerTestBit y_R 0 || x_R /= r) @@ -1223,7 +1230,7 @@ _verify_ecdsa_unrestricted _mul (SHA256.hash -> h) p (ECDSA r s) u1 = remQ (e * s_inv) u2 = remQ (r * s_inv) capR = add (_mul u1) (mul_unsafe p u2) - in if capR == _ZERO + in if capR == _CURVE_ZERO then False else let Affine (modQ -> v) _ = affine capR in v == r