btcec: Prevent static initialization of S256

This is achieved by introducing a new variable `halfOrder` on the
KoblitzCurve struct that is half the order.
This commit is contained in:
Steven Roose 2017-09-21 00:00:49 +02:00 committed by Dave Collins
parent 64d60f2ef2
commit 79445fbd97
2 changed files with 10 additions and 11 deletions

View file

@ -38,6 +38,7 @@ type KoblitzCurve struct {
*elliptic.CurveParams *elliptic.CurveParams
q *big.Int q *big.Int
H int // cofactor of the curve. 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 // byteSize is simply the bit size / 8 and is provided for convenience
// since it is calculated repeatedly. // since it is calculated repeatedly.
@ -912,9 +913,10 @@ func initS256() {
secp256k1.Gx = fromHex("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798") secp256k1.Gx = fromHex("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798")
secp256k1.Gy = fromHex("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8") secp256k1.Gy = fromHex("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8")
secp256k1.BitSize = 256 secp256k1.BitSize = 256
secp256k1.H = 1
secp256k1.q = new(big.Int).Div(new(big.Int).Add(secp256k1.P, secp256k1.q = new(big.Int).Div(new(big.Int).Add(secp256k1.P,
big.NewInt(1)), big.NewInt(4)) 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. // Provided for convenience since this gets computed repeatedly.
secp256k1.byteSize = secp256k1.BitSize / 8 secp256k1.byteSize = secp256k1.BitSize / 8

View file

@ -29,10 +29,6 @@ type Signature struct {
} }
var ( 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 // Used in RFC6979 implementation when testing the nonce for correctness
one = big.NewInt(1) one = big.NewInt(1)
@ -51,8 +47,8 @@ var (
func (sig *Signature) Serialize() []byte { func (sig *Signature) Serialize() []byte {
// low 'S' malleability breaker // low 'S' malleability breaker
sigS := sig.S sigS := sig.S
if sigS.Cmp(halforder) == 1 { if sigS.Cmp(S256().halfOrder) == 1 {
sigS = new(big.Int).Sub(order, sigS) sigS = new(big.Int).Sub(S256().N, sigS)
} }
// Ensure the encoded bytes for the r and s values are canonical and // Ensure the encoded bytes for the r and s values are canonical and
// thus suitable for DER encoding. // thus suitable for DER encoding.
@ -420,7 +416,8 @@ func RecoverCompact(curve *KoblitzCurve, signature,
func signRFC6979(privateKey *PrivateKey, hash []byte) (*Signature, error) { func signRFC6979(privateKey *PrivateKey, hash []byte) (*Signature, error) {
privkey := privateKey.ToECDSA() privkey := privateKey.ToECDSA()
N := order N := S256().N
halfOrder := S256().halfOrder
k := nonceRFC6979(privkey.D, hash) k := nonceRFC6979(privkey.D, hash)
inv := new(big.Int).ModInverse(k, N) inv := new(big.Int).ModInverse(k, N)
r, _ := privkey.Curve.ScalarBaseMult(k.Bytes()) r, _ := privkey.Curve.ScalarBaseMult(k.Bytes())
@ -438,7 +435,7 @@ func signRFC6979(privateKey *PrivateKey, hash []byte) (*Signature, error) {
s.Mul(s, inv) s.Mul(s, inv)
s.Mod(s, N) s.Mod(s, N)
if s.Cmp(halforder) == 1 { if s.Cmp(halfOrder) == 1 {
s.Sub(N, s) s.Sub(N, s)
} }
if s.Sign() == 0 { if s.Sign() == 0 {