Skip to content

Commit

Permalink
crypto/ed25519,crypto/rsa: make Equal methods constant time
Browse files Browse the repository at this point in the history
Fixes #53849
Updates #57752

Change-Id: I055564f31a47c79565b82bf9844fcf626989b295
Reviewed-on: https://go-review.googlesource.com/c/go/+/492955
Auto-Submit: Russ Cox <rsc@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
  • Loading branch information
FiloSottile authored and gopherbot committed May 17, 2023
1 parent b7e767b commit bf8571c
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 5 deletions.
5 changes: 3 additions & 2 deletions src/crypto/ed25519/ed25519.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"crypto/internal/edwards25519"
cryptorand "crypto/rand"
"crypto/sha512"
"crypto/subtle"
"errors"
"io"
"strconv"
Expand Down Expand Up @@ -46,7 +47,7 @@ func (pub PublicKey) Equal(x crypto.PublicKey) bool {
if !ok {
return false
}
return bytes.Equal(pub, xx)
return subtle.ConstantTimeCompare(pub, xx) == 1
}

// PrivateKey is the type of Ed25519 private keys. It implements [crypto.Signer].
Expand All @@ -65,7 +66,7 @@ func (priv PrivateKey) Equal(x crypto.PrivateKey) bool {
if !ok {
return false
}
return bytes.Equal(priv, xx)
return subtle.ConstantTimeCompare(priv, xx) == 1
}

// Seed returns the private key seed corresponding to priv. It is provided for
Expand Down
12 changes: 9 additions & 3 deletions src/crypto/rsa/rsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func (pub *PublicKey) Equal(x crypto.PublicKey) bool {
if !ok {
return false
}
return pub.N.Cmp(xx.N) == 0 && pub.E == xx.E
return bigIntEqual(pub.N, xx.N) && pub.E == xx.E
}

// OAEPOptions is an interface for passing options to OAEP decryption using the
Expand Down Expand Up @@ -130,20 +130,26 @@ func (priv *PrivateKey) Equal(x crypto.PrivateKey) bool {
if !ok {
return false
}
if !priv.PublicKey.Equal(&xx.PublicKey) || priv.D.Cmp(xx.D) != 0 {
if !priv.PublicKey.Equal(&xx.PublicKey) || !bigIntEqual(priv.D, xx.D) {
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 {
if !bigIntEqual(priv.Primes[i], xx.Primes[i]) {
return false
}
}
return true
}

// bigIntEqual reports whether a and b are equal leaking only their bit length
// through timing side-channels.
func bigIntEqual(a, b *big.Int) bool {
return subtle.ConstantTimeCompare(a.Bytes(), b.Bytes()) == 1
}

// 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
Expand Down

0 comments on commit bf8571c

Please sign in to comment.