From df04f9e47090a2fab9556035ed7deb978ff9e67a Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 18 Dec 2017 13:28:23 +0100 Subject: [PATCH 1/3] crypto: ensure that VerifySignature rejects malleable signatures It already rejected them when using libsecp256k1, make sure the nocgo version does the same thing. --- crypto/signature_nocgo.go | 3 +++ crypto/signature_test.go | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/crypto/signature_nocgo.go b/crypto/signature_nocgo.go index 78b99c02b0b2..822208e9a37d 100644 --- a/crypto/signature_nocgo.go +++ b/crypto/signature_nocgo.go @@ -87,6 +87,9 @@ func VerifySignature(pubkey, hash, signature []byte) bool { if err != nil { return false } + if !ValidateSignatureValues(0, sig.R, sig.S, true) { + return false + } return sig.Verify(hash, key) } diff --git a/crypto/signature_test.go b/crypto/signature_test.go index 5e2efc7e05a1..aecff76bfbda 100644 --- a/crypto/signature_test.go +++ b/crypto/signature_test.go @@ -75,6 +75,16 @@ func TestVerifySignature(t *testing.T) { } } +// This test checks that VerifySignature rejects malleable signatures with s > N/2. +func TestVerifySignatureMalleable(t *testing.T) { + sig := hexutil.MustDecode("0x638a54215d80a6713c8d523a6adc4e6e73652d859103a36b700851cb0e61b66b8ebfc1a610c57d732ec6e0a8f06a9a7a28df5051ece514702ff9cdff0b11f454") + key := hexutil.MustDecode("0x03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138") + msg := hexutil.MustDecode("0xd301ce462d3e639518f482c7f03821fec1e602018630ce621e1e7851c12343a6") + if VerifySignature(key, msg, sig) { + t.Error("VerifySignature returned true for malleable signature") + } +} + func TestDecompressPubkey(t *testing.T) { key, err := DecompressPubkey(testpubkeyc) if err != nil { From b6be57f42165d3b35b196ea09b55e206f4372951 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 20 Dec 2017 10:18:57 +0100 Subject: [PATCH 2/3] crypto: simplify check --- crypto/signature_nocgo.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crypto/signature_nocgo.go b/crypto/signature_nocgo.go index 822208e9a37d..f45a6202dcfe 100644 --- a/crypto/signature_nocgo.go +++ b/crypto/signature_nocgo.go @@ -87,7 +87,8 @@ func VerifySignature(pubkey, hash, signature []byte) bool { if err != nil { return false } - if !ValidateSignatureValues(0, sig.R, sig.S, true) { + // Reject malleable signatures. libsecp256k1 does this check but btcec doesn't. + if s.Cmp(secp256k1_halfN) > 0 { return false } return sig.Verify(hash, key) From 41c854a60fad2ad9bb732857445624c7214541db Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 20 Dec 2017 13:06:50 +0100 Subject: [PATCH 3/3] crypto: fix build --- crypto/signature_nocgo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/signature_nocgo.go b/crypto/signature_nocgo.go index f45a6202dcfe..f636b2377287 100644 --- a/crypto/signature_nocgo.go +++ b/crypto/signature_nocgo.go @@ -88,7 +88,7 @@ func VerifySignature(pubkey, hash, signature []byte) bool { return false } // Reject malleable signatures. libsecp256k1 does this check but btcec doesn't. - if s.Cmp(secp256k1_halfN) > 0 { + if sig.S.Cmp(secp256k1_halfN) > 0 { return false } return sig.Verify(hash, key)