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

@ -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

View file

@ -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 {