From 79445fbd97024a259f0dbd2b3d02a10073d9d146 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Thu, 21 Sep 2017 00:00:49 +0200 Subject: [PATCH] btcec: Prevent static initialization of S256 This is achieved by introducing a new variable `halfOrder` on the KoblitzCurve struct that is half the order. --- btcec/btcec.go | 8 +++++--- btcec/signature.go | 13 +++++-------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/btcec/btcec.go b/btcec/btcec.go index fe8ff901..5e7ce875 100644 --- a/btcec/btcec.go +++ b/btcec/btcec.go @@ -36,8 +36,9 @@ var ( // interface from crypto/elliptic. type KoblitzCurve struct { *elliptic.CurveParams - q *big.Int - H int // cofactor of the curve. + q *big.Int + H int // cofactor of the curve. + halfOrder *big.Int // half the order N // byteSize is simply the bit size / 8 and is provided for convenience // since it is calculated repeatedly. @@ -912,9 +913,10 @@ func initS256() { secp256k1.Gx = fromHex("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798") secp256k1.Gy = fromHex("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8") secp256k1.BitSize = 256 - secp256k1.H = 1 secp256k1.q = new(big.Int).Div(new(big.Int).Add(secp256k1.P, big.NewInt(1)), big.NewInt(4)) + secp256k1.H = 1 + secp256k1.halfOrder = new(big.Int).Rsh(secp256k1.N, 1) // Provided for convenience since this gets computed repeatedly. secp256k1.byteSize = secp256k1.BitSize / 8 diff --git a/btcec/signature.go b/btcec/signature.go index 21826f22..4392ab41 100644 --- a/btcec/signature.go +++ b/btcec/signature.go @@ -29,10 +29,6 @@ type Signature struct { } var ( - // Curve order and halforder, used to tame ECDSA malleability (see BIP-0062) - order = new(big.Int).Set(S256().N) - halforder = new(big.Int).Rsh(order, 1) - // Used in RFC6979 implementation when testing the nonce for correctness one = big.NewInt(1) @@ -51,8 +47,8 @@ var ( func (sig *Signature) Serialize() []byte { // low 'S' malleability breaker sigS := sig.S - if sigS.Cmp(halforder) == 1 { - sigS = new(big.Int).Sub(order, sigS) + if sigS.Cmp(S256().halfOrder) == 1 { + sigS = new(big.Int).Sub(S256().N, sigS) } // Ensure the encoded bytes for the r and s values are canonical and // thus suitable for DER encoding. @@ -420,7 +416,8 @@ func RecoverCompact(curve *KoblitzCurve, signature, func signRFC6979(privateKey *PrivateKey, hash []byte) (*Signature, error) { privkey := privateKey.ToECDSA() - N := order + N := S256().N + halfOrder := S256().halfOrder k := nonceRFC6979(privkey.D, hash) inv := new(big.Int).ModInverse(k, N) r, _ := privkey.Curve.ScalarBaseMult(k.Bytes()) @@ -438,7 +435,7 @@ func signRFC6979(privateKey *PrivateKey, hash []byte) (*Signature, error) { s.Mul(s, inv) s.Mod(s, N) - if s.Cmp(halforder) == 1 { + if s.Cmp(halfOrder) == 1 { s.Sub(N, s) } if s.Sign() == 0 {