Browse Source

make PrivateKey + Signature comparisons use constant time comparisons

Fixes https://github.com/tendermint/go-crypto/issues/43

Avoid susceptibility to timing/side channel attacks by ensuring
that private key and signature comparisons use
`subtle.ConstantTimeCompare`
instead of
`bytes.Equal`
pull/1782/head
Emmanuel Odeke 7 years ago
parent
commit
3df2ca128d
No known key found for this signature in database GPG Key ID: 1CA47A292F89DD40
2 changed files with 22 additions and 6 deletions
  1. +11
    -3
      priv_key.go
  2. +11
    -3
      signature.go

+ 11
- 3
priv_key.go View File

@ -1,7 +1,7 @@
package crypto package crypto
import ( import (
"bytes"
"crypto/subtle"
secp256k1 "github.com/btcsuite/btcd/btcec" secp256k1 "github.com/btcsuite/btcd/btcec"
"github.com/tendermint/ed25519" "github.com/tendermint/ed25519"
@ -57,7 +57,11 @@ func (privKey PrivKeyEd25519) PubKey() PubKey {
func (privKey PrivKeyEd25519) Equals(other PrivKey) bool { func (privKey PrivKeyEd25519) Equals(other PrivKey) bool {
if otherEd, ok := other.Unwrap().(PrivKeyEd25519); ok { 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 { } else {
return false return false
} }
@ -144,7 +148,11 @@ func (privKey PrivKeySecp256k1) PubKey() PubKey {
func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool { func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool {
if otherSecp, ok := other.Unwrap().(PrivKeySecp256k1); ok { 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 { } else {
return false return false
} }


+ 11
- 3
signature.go View File

@ -1,7 +1,7 @@
package crypto package crypto
import ( import (
"bytes"
"crypto/subtle"
"fmt" "fmt"
"github.com/tendermint/go-wire" "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 { func (sig SignatureEd25519) Equals(other Signature) bool {
if otherEd, ok := other.Unwrap().(SignatureEd25519); ok { 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 { } else {
return false return false
} }
@ -82,7 +86,11 @@ func (sig SignatureSecp256k1) String() string { return fmt.Sprintf("/%X.../", Fi
func (sig SignatureSecp256k1) Equals(other Signature) bool { func (sig SignatureSecp256k1) Equals(other Signature) bool {
if otherEd, ok := other.Unwrap().(SignatureSecp256k1); ok { 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 { } else {
return false return false
} }


Loading…
Cancel
Save