aboutsummaryrefslogtreecommitdiff
path: root/src/crypto/ecdsa/ecdsa.go
diff options
context:
space:
mode:
authorFilippo Valsorda <filippo@golang.org>2020-04-08 17:39:57 -0400
committerFilippo Valsorda <filippo@golang.org>2020-04-08 17:48:41 -0400
commite067ce5225300a87ae6fe3c48e73102f6fa9368d (patch)
tree3b9335e0023a30f50c3261545019a2f9bb1bab97 /src/crypto/ecdsa/ecdsa.go
parent79284c28734bf854f44106835b5578ead75eb547 (diff)
parent9baafabac9a84813a336f068862207d2bb06d255 (diff)
downloadgo-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.go62
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
}