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 12197864a9b2b09ac24b4b9e594d6d9ec8a295f4
parent ac4037e56cea6626e60fe1a0c448526247be9037
Author: Jared Tobin <jared@jtobin.io>
Date:   Sat,  1 Aug 2026 12:29:49 -0230

lib: retry on the degenerate ecdsa signing cases

gen_k checked only k < q, admitting k = 0; _mul then failed and
signing returned Nothing rather than retrying, where RFC6979 requires
k in [1, q - 1]. ge is exactly that predicate.

_sign_ecdsa likewise retried on r = 0 but not on s = 0, emitting a
signature that cannot verify. SEC1-v2 4.1.3 retries on either.

Both are 2 ^ -256 events.

Diffstat:
Mlib/Crypto/Curve/Secp256k1.hs | 9+++++----
1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/lib/Crypto/Curve/Secp256k1.hs b/lib/Crypto/Curve/Secp256k1.hs @@ -1314,7 +1314,8 @@ _sign_ecdsa _mul ty hf _SECRET m DRBG.wipe g pure Nothing Just (r, s) - | W.eq_vartime r 0 -> sign_loop g -- negligible probability + -- sec1-v2 4.1.3 retries on either being zero + | W.eq_vartime r 0 || W.eq_vartime s 0 -> sign_loop g | otherwise -> do DRBG.wipe g let !sig = Just $! ECDSA r s @@ -1332,9 +1333,9 @@ gen_k g = loop g where Left {} -> error "ppad-secp256k1: internal error (please report a bug!)" Right bs -> do let can = bits2int bs - case W.cmp_vartime can _CURVE_Q of - LT -> pure can - _ -> loop drbg -- 2 ^ -128 probability + if ge can -- rfc6979 requires k in [1, q - 1] + then pure can + else loop drbg -- 2 ^ -128 probability {-# INLINE gen_k #-} -- | Verify a "low-s" ECDSA signature for the provided message and