From 1461d7a248e720e6b078fa7f1d6df7e11eec68e1 Mon Sep 17 00:00:00 2001 From: alexvanin Date: Sun, 1 Mar 2020 16:50:38 +0300 Subject: [PATCH 1/2] rfc6979: Add leading zeros if `r` or `s` has less than 32 bytes SignECDSA function returns two coordinates on elliptic curve. Catenation of these coordinates is a 64 byte signature. If one of these coordinates have less than 32 significant bytes, then it should have leading zeros. --- rfc6979.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/rfc6979.go b/rfc6979.go index 007198a..42f6469 100644 --- a/rfc6979.go +++ b/rfc6979.go @@ -38,7 +38,18 @@ func SignRFC6979(key *ecdsa.PrivateKey, msg []byte) ([]byte, error) { return nil, ErrEmptyPrivateKey } r, s := rfc6979.SignECDSA(key, hashBytesRFC6979(msg), sha256.New) - return append(r.Bytes(), s.Bytes()...), nil + rBytes, sBytes := r.Bytes(), s.Bytes() + signature := make([]byte, RFC6979SignatureSize) + + // if `r` has less than 32 bytes, add leading zeros + ind := RFC6979SignatureSize/2 - len(rBytes) + copy(signature[ind:], rBytes) + + // if `s` has less than 32 bytes, add leading zeros + ind = RFC6979SignatureSize - len(sBytes) + copy(signature[ind:], sBytes) + + return signature, nil } func decodeSignature(sig []byte) (*big.Int, *big.Int, error) { From c1e43f87272ef72d9970631465617a9a5b3111c0 Mon Sep 17 00:00:00 2001 From: alexvanin Date: Sun, 1 Mar 2020 16:57:24 +0300 Subject: [PATCH 2/2] rfc6979: Add tests for short `r` and `s` coordinates --- rfc6979_test.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/rfc6979_test.go b/rfc6979_test.go index 5791bfd..c42b037 100644 --- a/rfc6979_test.go +++ b/rfc6979_test.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "testing" + "github.com/nspcc-dev/neofs-crypto/test" "github.com/stretchr/testify/require" ) @@ -83,3 +84,23 @@ func TestRFC6979(t *testing.T) { } } } + +func TestRFC6979_ShortDecodePoints(t *testing.T) { + key := test.DecodeKey(1) + + msgs := []string{ + "6341922933e156ea5a53b8ea3fa4a80c", // this msg has 31 byte `s` point + "61b863d81f72e0e0d0353b1cb90d62ce", // this msg has 31 byte 'r' point + } + + for i := range msgs { + msg, err := hex.DecodeString(msgs[i]) + require.NoError(t, err) + + signature, err := SignRFC6979(key, msg) + require.NoError(t, err, msgs[i]) + + err = VerifyRFC6979(&key.PublicKey, msg, signature) + require.NoError(t, err, msgs[i]) + } +}