Allow to use hash in Sign*/Verify*
Sometimes having a whole buffer in memory isn't desired. New interface allows us to provide hashes instead.
This commit is contained in:
parent
e9d1b1884c
commit
225b24f7f4
4 changed files with 65 additions and 10 deletions
21
ecdsa.go
21
ecdsa.go
|
@ -124,11 +124,17 @@ func hashBytes(data []byte) []byte {
|
||||||
// Verify verifies the signature of msg using the public key pub. It returns
|
// Verify verifies the signature of msg using the public key pub. It returns
|
||||||
// nil only if signature is valid.
|
// nil only if signature is valid.
|
||||||
func Verify(pub *ecdsa.PublicKey, msg, sig []byte) error {
|
func Verify(pub *ecdsa.PublicKey, msg, sig []byte) error {
|
||||||
if r, s := unmarshalXY(sig); r == nil || s == nil {
|
return VerifyHash(pub, hashBytes(msg), sig)
|
||||||
return ErrCannotUnmarshal
|
}
|
||||||
} else if pub == nil {
|
|
||||||
|
// VerifyHash verifies the signature of msg using it's hash the public key pub.
|
||||||
|
// It returns nil only if signature is valid.
|
||||||
|
func VerifyHash(pub *ecdsa.PublicKey, msgHash, sig []byte) error {
|
||||||
|
if pub == nil {
|
||||||
return ErrEmptyPublicKey
|
return ErrEmptyPublicKey
|
||||||
} else if !ecdsa.Verify(pub, hashBytes(msg), r, s) {
|
} else if r, s := unmarshalXY(sig); r == nil || s == nil {
|
||||||
|
return ErrCannotUnmarshal
|
||||||
|
} else if !ecdsa.Verify(pub, msgHash, r, s) {
|
||||||
return errors.Wrapf(ErrInvalidSignature, "%0x : %0x", r, s)
|
return errors.Wrapf(ErrInvalidSignature, "%0x : %0x", r, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +146,12 @@ func Verify(pub *ecdsa.PublicKey, msg, sig []byte) error {
|
||||||
// will be truncated to that length. It returns the signature as slice bytes.
|
// will be truncated to that length. It returns the signature as slice bytes.
|
||||||
// The security of the private key depends on the entropy of rand.
|
// The security of the private key depends on the entropy of rand.
|
||||||
func Sign(key *ecdsa.PrivateKey, msg []byte) ([]byte, error) {
|
func Sign(key *ecdsa.PrivateKey, msg []byte) ([]byte, error) {
|
||||||
x, y, err := ecdsa.Sign(rand.Reader, key, hashBytes(msg))
|
return SignHash(key, hashBytes(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignHash signs message using it's hash and private key.
|
||||||
|
func SignHash(key *ecdsa.PrivateKey, msgHash []byte) ([]byte, error) {
|
||||||
|
x, y, err := ecdsa.Sign(rand.Reader, key, msgHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/sha512"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
@ -125,6 +126,17 @@ func TestSignVerify(t *testing.T) {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("using prepared hash", func(t *testing.T) {
|
||||||
|
var (
|
||||||
|
data = []byte("Hello world")
|
||||||
|
sum = sha512.Sum512(data)
|
||||||
|
key = test.DecodeKey(0)
|
||||||
|
)
|
||||||
|
sig, err := SignHash(key, sum[:])
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, VerifyHash(&key.PublicKey, sum[:], sig))
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("low level", func(t *testing.T) {
|
t.Run("low level", func(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
data = []byte("Hello world")
|
data = []byte("Hello world")
|
||||||
|
|
22
rfc6979.go
22
rfc6979.go
|
@ -34,10 +34,16 @@ func hashBytesRFC6979(data []byte) []byte {
|
||||||
// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
|
// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
|
||||||
// to the byte-length of the subgroup. This function does not perform that.
|
// to the byte-length of the subgroup. This function does not perform that.
|
||||||
func SignRFC6979(key *ecdsa.PrivateKey, msg []byte) ([]byte, error) {
|
func SignRFC6979(key *ecdsa.PrivateKey, msg []byte) ([]byte, error) {
|
||||||
|
return SignRFC6979Hash(key, hashBytesRFC6979(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignRFC6979Hash signs sha256 hash of the message using the private key.
|
||||||
|
func SignRFC6979Hash(key *ecdsa.PrivateKey, msgHash []byte) ([]byte, error) {
|
||||||
if key == nil {
|
if key == nil {
|
||||||
return nil, ErrEmptyPrivateKey
|
return nil, ErrEmptyPrivateKey
|
||||||
}
|
}
|
||||||
r, s := rfc6979.SignECDSA(key, hashBytesRFC6979(msg), sha256.New)
|
|
||||||
|
r, s := rfc6979.SignECDSA(key, msgHash, sha256.New)
|
||||||
rBytes, sBytes := r.Bytes(), s.Bytes()
|
rBytes, sBytes := r.Bytes(), s.Bytes()
|
||||||
signature := make([]byte, RFC6979SignatureSize)
|
signature := make([]byte, RFC6979SignatureSize)
|
||||||
|
|
||||||
|
@ -73,3 +79,17 @@ func VerifyRFC6979(key *ecdsa.PublicKey, msg, sig []byte) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VerifyRFC6979 verifies the signature of msg using the public key. It
|
||||||
|
// return nil only if signature is valid.
|
||||||
|
func VerifyRFC6979Hash(key *ecdsa.PublicKey, msgHash, sig []byte) error {
|
||||||
|
if key == nil {
|
||||||
|
return ErrEmptyPublicKey
|
||||||
|
} else if r, s, err := decodeSignature(sig); err != nil {
|
||||||
|
return err
|
||||||
|
} else if !ecdsa.Verify(key, msgHash, r, s) {
|
||||||
|
return ErrWrongSignature
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package crypto
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -63,12 +64,23 @@ func TestRFC6979(t *testing.T) {
|
||||||
{ // Generated by Go
|
{ // Generated by Go
|
||||||
sig := data[offset : offset+RFC6979SignatureSize]
|
sig := data[offset : offset+RFC6979SignatureSize]
|
||||||
|
|
||||||
res, err := SignRFC6979(key, body)
|
{ // SignRFC6979
|
||||||
require.NoError(t, err)
|
res, err := SignRFC6979(key, body)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, sig, res, "step: %d, %02x", i, res)
|
require.Equal(t, sig, res, "step: %d, %02x", i, res)
|
||||||
|
|
||||||
require.NoErrorf(t, VerifyRFC6979(pub, body, sig), "step: %d", i)
|
require.NoErrorf(t, VerifyRFC6979(pub, body, sig), "step: %d", i)
|
||||||
|
}
|
||||||
|
{ // SignRFC6979Hash
|
||||||
|
sum := sha256.Sum256(body)
|
||||||
|
res, err := SignRFC6979Hash(key, sum[:])
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, sig, res, "step: %d, %02x", i, res)
|
||||||
|
|
||||||
|
require.NoErrorf(t, VerifyRFC6979Hash(pub, sum[:], sig), "step: %d", i)
|
||||||
|
}
|
||||||
offset += RFC6979SignatureSize
|
offset += RFC6979SignatureSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue