mirror of
https://github.com/golang/go.git
synced 2025-05-16 12:54:37 +00:00
crypto/rsa,crypto/ecdsa,crypto/ed25519: implement PrivateKey.Equal
Fixes #38190 Change-Id: I10766068ee18974e81b3bd78ee0b4d83cc9d1a8c Reviewed-on: https://go-review.googlesource.com/c/go/+/231417 Run-TryBot: Filippo Valsorda <filippo@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Katie Hockman <katie@golang.org>
This commit is contained in:
parent
a6c6e59655
commit
a8e83d51a0
@ -62,6 +62,9 @@ type PublicKey struct {
|
||||
X, Y *big.Int
|
||||
}
|
||||
|
||||
// Any methods implemented on PublicKey might need to also be implemented on
|
||||
// PrivateKey, as the latter embeds the former and will expose its methods.
|
||||
|
||||
// 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.
|
||||
@ -91,6 +94,17 @@ func (priv *PrivateKey) Public() crypto.PublicKey {
|
||||
return &priv.PublicKey
|
||||
}
|
||||
|
||||
// Equal reports whether priv and x have the same value.
|
||||
//
|
||||
// See PublicKey.Equal for details on how Curve is compared.
|
||||
func (priv *PrivateKey) Equal(x crypto.PrivateKey) bool {
|
||||
xx, ok := x.(*PrivateKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return priv.PublicKey.Equal(&xx.PublicKey) && priv.D.Cmp(xx.D) == 0
|
||||
}
|
||||
|
||||
// Sign signs digest with priv, reading randomness from rand. The opts argument
|
||||
// is not currently used but, in keeping with the crypto.Signer interface,
|
||||
// should be the hash function used to digest the message.
|
||||
|
@ -23,23 +23,32 @@ func testEqual(t *testing.T, c elliptic.Curve) {
|
||||
if !public.Equal(crypto.Signer(private).Public().(*ecdsa.PublicKey)) {
|
||||
t.Errorf("private.Public() is not Equal to public: %q", public)
|
||||
}
|
||||
if !private.Equal(private) {
|
||||
t.Errorf("private key is not equal to itself: %v", private)
|
||||
}
|
||||
|
||||
enc, err := x509.MarshalPKIXPublicKey(public)
|
||||
enc, err := x509.MarshalPKCS8PrivateKey(private)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
decoded, err := x509.ParsePKIXPublicKey(enc)
|
||||
decoded, err := x509.ParsePKCS8PrivateKey(enc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !public.Equal(decoded) {
|
||||
if !public.Equal(decoded.(crypto.Signer).Public()) {
|
||||
t.Errorf("public key is not equal to itself after decoding: %v", public)
|
||||
}
|
||||
if !private.Equal(decoded) {
|
||||
t.Errorf("private key is not equal to itself after decoding: %v", private)
|
||||
}
|
||||
|
||||
other, _ := ecdsa.GenerateKey(c, rand.Reader)
|
||||
if public.Equal(other) {
|
||||
if public.Equal(other.Public()) {
|
||||
t.Errorf("different public keys are Equal")
|
||||
}
|
||||
if private.Equal(other) {
|
||||
t.Errorf("different private keys are Equal")
|
||||
}
|
||||
|
||||
// Ensure that keys with the same coordinates but on different curves
|
||||
// aren't considered Equal.
|
||||
|
@ -40,6 +40,9 @@ const (
|
||||
// PublicKey is the type of Ed25519 public keys.
|
||||
type PublicKey []byte
|
||||
|
||||
// Any methods implemented on PublicKey might need to also be implemented on
|
||||
// PrivateKey, as the latter embeds the former and will expose its methods.
|
||||
|
||||
// Equal reports whether pub and x have the same value.
|
||||
func (pub PublicKey) Equal(x crypto.PublicKey) bool {
|
||||
xx, ok := x.(PublicKey)
|
||||
@ -59,6 +62,15 @@ func (priv PrivateKey) Public() crypto.PublicKey {
|
||||
return PublicKey(publicKey)
|
||||
}
|
||||
|
||||
// Equal reports whether priv and x have the same value.
|
||||
func (priv PrivateKey) Equal(x crypto.PrivateKey) bool {
|
||||
xx, ok := x.(PrivateKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return bytes.Equal(priv, xx)
|
||||
}
|
||||
|
||||
// Seed returns the private key seed corresponding to priv. It is provided for
|
||||
// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds
|
||||
// in this package.
|
||||
|
@ -113,14 +113,20 @@ func TestEqual(t *testing.T) {
|
||||
if !public.Equal(public) {
|
||||
t.Errorf("public key is not equal to itself: %q", public)
|
||||
}
|
||||
if !public.Equal(crypto.Signer(private).Public().(PublicKey)) {
|
||||
if !public.Equal(crypto.Signer(private).Public()) {
|
||||
t.Errorf("private.Public() is not Equal to public: %q", public)
|
||||
}
|
||||
if !private.Equal(private) {
|
||||
t.Errorf("private key is not equal to itself: %q", private)
|
||||
}
|
||||
|
||||
other, _, _ := GenerateKey(rand.Reader)
|
||||
if public.Equal(other) {
|
||||
otherPub, otherPriv, _ := GenerateKey(rand.Reader)
|
||||
if public.Equal(otherPub) {
|
||||
t.Errorf("different public keys are Equal")
|
||||
}
|
||||
if private.Equal(otherPriv) {
|
||||
t.Errorf("different private keys are Equal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGolden(t *testing.T) {
|
||||
|
@ -22,21 +22,30 @@ func TestEqual(t *testing.T) {
|
||||
if !public.Equal(crypto.Signer(private).Public().(*rsa.PublicKey)) {
|
||||
t.Errorf("private.Public() is not Equal to public: %q", public)
|
||||
}
|
||||
if !private.Equal(private) {
|
||||
t.Errorf("private key is not equal to itself: %v", private)
|
||||
}
|
||||
|
||||
enc, err := x509.MarshalPKIXPublicKey(public)
|
||||
enc, err := x509.MarshalPKCS8PrivateKey(private)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
decoded, err := x509.ParsePKIXPublicKey(enc)
|
||||
decoded, err := x509.ParsePKCS8PrivateKey(enc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !public.Equal(decoded) {
|
||||
if !public.Equal(decoded.(crypto.Signer).Public()) {
|
||||
t.Errorf("public key is not equal to itself after decoding: %v", public)
|
||||
}
|
||||
if !private.Equal(decoded) {
|
||||
t.Errorf("private key is not equal to itself after decoding: %v", private)
|
||||
}
|
||||
|
||||
other, _ := rsa.GenerateKey(rand.Reader, 512)
|
||||
if public.Equal(other) {
|
||||
if public.Equal(other.Public()) {
|
||||
t.Errorf("different public keys are Equal")
|
||||
}
|
||||
if private.Equal(other) {
|
||||
t.Errorf("different private keys are Equal")
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,9 @@ type PublicKey struct {
|
||||
E int // public exponent
|
||||
}
|
||||
|
||||
// Any methods implemented on PublicKey might need to also be implemented on
|
||||
// PrivateKey, as the latter embeds the former and will expose its methods.
|
||||
|
||||
// Size returns the modulus size in bytes. Raw signatures and ciphertexts
|
||||
// for or by this public key will have the same size.
|
||||
func (pub *PublicKey) Size() int {
|
||||
@ -109,6 +112,27 @@ func (priv *PrivateKey) Public() crypto.PublicKey {
|
||||
return &priv.PublicKey
|
||||
}
|
||||
|
||||
// Equal reports whether priv and x have equivalent values. It ignores
|
||||
// Precomputed values.
|
||||
func (priv *PrivateKey) Equal(x crypto.PrivateKey) bool {
|
||||
xx, ok := x.(*PrivateKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if !priv.PublicKey.Equal(&xx.PublicKey) || priv.D.Cmp(xx.D) != 0 {
|
||||
return false
|
||||
}
|
||||
if len(priv.Primes) != len(xx.Primes) {
|
||||
return false
|
||||
}
|
||||
for i := range priv.Primes {
|
||||
if priv.Primes[i].Cmp(xx.Primes[i]) != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Sign signs digest with priv, reading randomness from rand. If opts is a
|
||||
// *PSSOptions then the PSS algorithm will be used, otherwise PKCS#1 v1.5 will
|
||||
// be used. digest must be the result of hashing the input message using
|
||||
|
Loading…
x
Reference in New Issue
Block a user