diff --git a/signature.go b/signature.go index 6826363d5..2c0e17af7 100644 --- a/signature.go +++ b/signature.go @@ -25,6 +25,12 @@ type Signature struct { S *big.Int } +// curve order and halforder, used to tame ECDSA malleability (see BIP-0062) +var ( + order = new(big.Int).Set(S256().N) + halforder = new(big.Int).Rsh(order, 1) +) + // Serialize returns the ECDSA signature in the more strict DER format. Note // that the serialized bytes returned do not include the appended hash type // used in Bitcoin signature scripts. @@ -33,10 +39,15 @@ type Signature struct { // // 0x30 0x02 r 0x02 s func (sig *Signature) Serialize() []byte { + // low 'S' malleability breaker + sigS := sig.S + if sigS.Cmp(halforder) == 1 { + sigS = new(big.Int).Sub(order, sigS) + } // Ensure the encoded bytes for the r and s values are canonical and // thus suitable for DER encoding. rb := canonicalizeInt(sig.R) - sb := canonicalizeInt(sig.S) + sb := canonicalizeInt(sigS) // total length of returned signature is 1 byte for each magic and // length (6 total), plus lengths of r and s diff --git a/signature_test.go b/signature_test.go index bb4c2e80e..8ea3b11aa 100644 --- a/signature_test.go +++ b/signature_test.go @@ -391,7 +391,7 @@ func TestSignatureSerialize(t *testing.T) { "valid 3 - s most significant bit is one", &btcec.Signature{ R: fromHex("1cadddc2838598fee7dc35a12b340c6bde8b389f7bfd19a1252a17c4b5ed2d71"), - S: fromHex("00c1a251bbecb14b058a8bd77f65de87e51c47e95904f4c0e9d52eddc21c1415ac"), + S: new(big.Int).Add(fromHex("00c1a251bbecb14b058a8bd77f65de87e51c47e95904f4c0e9d52eddc21c1415ac"), btcec.S256().N), }, []byte{ 0x30, 0x45, 0x02, 0x20, 0x1c, 0xad, 0xdd, 0xc2,