diff options
author | Filippo Valsorda <filippo@golang.org> | 2020-04-08 17:39:57 -0400 |
---|---|---|
committer | Filippo Valsorda <filippo@golang.org> | 2020-04-08 17:48:41 -0400 |
commit | e067ce5225300a87ae6fe3c48e73102f6fa9368d (patch) | |
tree | 3b9335e0023a30f50c3261545019a2f9bb1bab97 /src/crypto/ecdsa/ecdsa.go | |
parent | 79284c28734bf854f44106835b5578ead75eb547 (diff) | |
parent | 9baafabac9a84813a336f068862207d2bb06d255 (diff) | |
download | go-e067ce5225300a87ae6fe3c48e73102f6fa9368d.tar.gz go-e067ce5225300a87ae6fe3c48e73102f6fa9368d.zip |
[dev.boringcrypto] all: merge master into dev.boringcrypto
Change-Id: I2dcec316fd08d91db4183fb9d3b9afde65cc248f
Diffstat (limited to 'src/crypto/ecdsa/ecdsa.go')
-rw-r--r-- | src/crypto/ecdsa/ecdsa.go | 62 |
1 files changed, 55 insertions, 7 deletions
diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go index e4e580fada..d10e354c76 100644 --- a/src/crypto/ecdsa/ecdsa.go +++ b/src/crypto/ecdsa/ecdsa.go @@ -33,10 +33,12 @@ import ( "crypto/elliptic" "crypto/internal/randutil" "crypto/sha512" - "encoding/asn1" "errors" "io" "math/big" + + "golang.org/x/crypto/cryptobyte" + "golang.org/x/crypto/cryptobyte/asn1" ) import ( @@ -67,6 +69,24 @@ type PublicKey struct { boring unsafe.Pointer } +// Equal reports whether pub and x have the same value. +// +// Two keys are only considered to have the same value if they have the same Curve value. +// Note that for example elliptic.P256() and elliptic.P256().Params() are different +// values, as the latter is a generic not constant time implementation. +func (pub *PublicKey) Equal(x crypto.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + return pub.X.Cmp(xx.X) == 0 && pub.Y.Cmp(xx.Y) == 0 && + // Standard library Curve implementations are singletons, so this check + // will work for those. Other Curves might be equivalent even if not + // singletons, but there is no definitive way to check for that, and + // better to err on the side of safety. + pub.Curve == xx.Curve +} + // PrivateKey represents an ECDSA private key. type PrivateKey struct { PublicKey @@ -75,10 +95,6 @@ type PrivateKey struct { boring unsafe.Pointer } -type ecdsaSignature struct { - R, S *big.Int -} - // Public returns the public key corresponding to priv. func (priv *PrivateKey) Public() crypto.PublicKey { return &priv.PublicKey @@ -106,7 +122,12 @@ func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOp return nil, err } - return asn1.Marshal(ecdsaSignature{r, s}) + var b cryptobyte.Builder + b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1BigInt(r) + b.AddASN1BigInt(s) + }) + return b.Bytes() } var one = new(big.Int).SetInt64(1) @@ -186,7 +207,7 @@ var errZeroParam = errors.New("zero parameter") // Sign signs a hash (which should be the result of hashing a larger message) // using the private key, priv. If the hash is longer than the bit-length of the -// private key's curve order, the hash will be truncated to that length. It +// private key's curve order, the hash will be truncated to that length. It // returns the signature as a pair of integers. The security of the private key // depends on the entropy of rand. func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { @@ -274,6 +295,15 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err return } +// SignASN1 signs a hash (which should be the result of hashing a larger message) +// using the private key, priv. If the hash is longer than the bit-length of the +// private key's curve order, the hash will be truncated to that length. It +// returns the ASN.1 encoded signature. The security of the private key +// depends on the entropy of rand. +func SignASN1(rand io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) { + return priv.Sign(rand, hash, nil) +} + // Verify verifies the signature in r, s of hash using the public key, pub. Its // return value records whether the signature is valid. func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { @@ -327,6 +357,24 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { return x.Cmp(r) == 0 } +// VerifyASN1 verifies the ASN.1 encoded signature, sig, of hash using the +// public key, pub. Its return value records whether the signature is valid. +func VerifyASN1(pub *PublicKey, hash, sig []byte) bool { + var ( + r, s = &big.Int{}, &big.Int{} + inner cryptobyte.String + ) + input := cryptobyte.String(sig) + if !input.ReadASN1(&inner, asn1.SEQUENCE) || + !input.Empty() || + !inner.ReadASN1Integer(r) || + !inner.ReadASN1Integer(s) || + !inner.Empty() { + return false + } + return Verify(pub, hash, r, s) +} + type zr struct { io.Reader } |