diff --git a/priv_key.go b/priv_key.go index 0c6bd2ae7..456985615 100644 --- a/priv_key.go +++ b/priv_key.go @@ -1,7 +1,7 @@ package crypto import ( - "bytes" + "crypto/subtle" secp256k1 "github.com/btcsuite/btcd/btcec" "github.com/tendermint/ed25519" @@ -57,7 +57,11 @@ func (privKey PrivKeyEd25519) PubKey() PubKey { func (privKey PrivKeyEd25519) Equals(other PrivKey) bool { if otherEd, ok := other.Unwrap().(PrivKeyEd25519); ok { - return bytes.Equal(privKey[:], otherEd[:]) + // It is essential that we constant time compare + // private keys and signatures instead of bytes.Equal, + // to avoid susceptibility to timing/side channel attacks. + // See Issue https://github.com/tendermint/go-crypto/issues/43 + return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 0 } else { return false } @@ -144,7 +148,11 @@ func (privKey PrivKeySecp256k1) PubKey() PubKey { func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool { if otherSecp, ok := other.Unwrap().(PrivKeySecp256k1); ok { - return bytes.Equal(privKey[:], otherSecp[:]) + // It is essential that we constant time compare + // private keys and signatures instead of bytes.Equal, + // to avoid susceptibility to timing/side channel attacks. + // See Issue https://github.com/tendermint/go-crypto/issues/43 + return subtle.ConstantTimeCompare(privKey[:], otherSecp[:]) == 0 } else { return false } diff --git a/signature.go b/signature.go index 5b1d6cb05..fb07aba96 100644 --- a/signature.go +++ b/signature.go @@ -1,7 +1,7 @@ package crypto import ( - "bytes" + "crypto/subtle" "fmt" "github.com/tendermint/go-wire" @@ -46,7 +46,11 @@ func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fing func (sig SignatureEd25519) Equals(other Signature) bool { if otherEd, ok := other.Unwrap().(SignatureEd25519); ok { - return bytes.Equal(sig[:], otherEd[:]) + // It is essential that we constant time compare + // private keys and signatures instead of bytes.Equal, + // to avoid susceptibility to timing/side channel attacks. + // See Issue https://github.com/tendermint/go-crypto/issues/43 + return subtle.ConstantTimeCompare(sig[:], otherEd[:]) == 0 } else { return false } @@ -82,7 +86,11 @@ func (sig SignatureSecp256k1) String() string { return fmt.Sprintf("/%X.../", Fi func (sig SignatureSecp256k1) Equals(other Signature) bool { if otherEd, ok := other.Unwrap().(SignatureSecp256k1); ok { - return bytes.Equal(sig[:], otherEd[:]) + // It is essential that we constant time compare + // private keys and signatures instead of bytes.Equal, + // to avoid susceptibility to timing/side channel attacks. + // See Issue https://github.com/tendermint/go-crypto/issues/43 + return subtle.ConstantTimeCompare(sig[:], otherEd[:]) == 0 } else { return false }