diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 707d37834..bdc2a7314 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -39,6 +39,8 @@ IMPROVEMENTS: - [consensus] [\#2169](https://github.com/cosmos/cosmos-sdk/issues/2169) add additional metrics - [p2p] [\#2169](https://github.com/cosmos/cosmos-sdk/issues/2169) add additional metrics - [config] \#2232 added ValidateBasic method, which performs basic checks +- [crypto/ed25519] \#2558 Switch to use latest `golang.org/x/crypto` through our fork at + github.com/tendermint/crypto - [tools] \#2238 Binary dependencies are now locked to a specific git commit - [crypto] \#2099 make crypto random use chacha, and have forward secrecy of generated randomness diff --git a/Gopkg.lock b/Gopkg.lock index 8deb06378..0f70bb2f7 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -364,18 +364,6 @@ pruneopts = "UT" revision = "e5840949ff4fff0c56f9b6a541e22b63581ea9df" -[[projects]] - branch = "master" - digest = "1:087aaa7920e5d0bf79586feb57ce01c35c830396ab4392798112e8aae8c47722" - name = "github.com/tendermint/ed25519" - packages = [ - ".", - "edwards25519", - "extra25519", - ] - pruneopts = "UT" - revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057" - [[projects]] digest = "1:e0a2a4be1e20c305badc2b0a7a9ab7fef6da500763bec23ab81df3b5f9eec9ee" name = "github.com/tendermint/go-amino" @@ -385,14 +373,15 @@ version = "v0.12.0-rc0" [[projects]] - branch = "master" - digest = "1:c31a37cafc12315b8bd745c8ad6a006ac25350472488162a821e557b3e739d67" + digest = "1:72b71e3a29775e5752ed7a8012052a3dee165e27ec18cedddae5288058f09acf" name = "golang.org/x/crypto" packages = [ "bcrypt", "blowfish", "chacha20poly1305", "curve25519", + "ed25519", + "ed25519/internal/edwards25519", "hkdf", "internal/chacha20", "internal/subtle", @@ -405,7 +394,8 @@ "salsa20/salsa", ] pruneopts = "UT" - revision = "56440b844dfe139a8ac053f4ecac0b20b79058f4" + revision = "3764759f34a542a3aef74d6b02e35be7ab893bba" + source = "github.com/tendermint/crypto" [[projects]] digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" @@ -543,12 +533,11 @@ "github.com/syndtr/goleveldb/leveldb/iterator", "github.com/syndtr/goleveldb/leveldb/opt", "github.com/tendermint/btcd/btcec", - "github.com/tendermint/ed25519", - "github.com/tendermint/ed25519/extra25519", "github.com/tendermint/go-amino", "golang.org/x/crypto/bcrypt", "golang.org/x/crypto/chacha20poly1305", "golang.org/x/crypto/curve25519", + "golang.org/x/crypto/ed25519", "golang.org/x/crypto/hkdf", "golang.org/x/crypto/nacl/box", "golang.org/x/crypto/nacl/secretbox", diff --git a/Gopkg.toml b/Gopkg.toml index d3bca19e8..07ff3c534 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -72,6 +72,11 @@ ## Some repos dont have releases. ## Pin to revision +[[constraint]] + name = "golang.org/x/crypto" + source = "github.com/tendermint/crypto" + revision = "3764759f34a542a3aef74d6b02e35be7ab893bba" + [[override]] name = "github.com/jmhodges/levigo" revision = "c42d9e0ca023e2198120196f842701bb4c55d7b9" diff --git a/crypto/armor/armor.go b/crypto/armor/armor.go index c15d070e6..e3b29a971 100644 --- a/crypto/armor/armor.go +++ b/crypto/armor/armor.go @@ -5,7 +5,7 @@ import ( "fmt" "io/ioutil" - "golang.org/x/crypto/openpgp/armor" + "golang.org/x/crypto/openpgp/armor" // forked to github.com/tendermint/crypto ) func EncodeArmor(blockType string, headers map[string]string, data []byte) string { diff --git a/crypto/ed25519/ed25519.go b/crypto/ed25519/ed25519.go index c55b3588f..c2bed6ab1 100644 --- a/crypto/ed25519/ed25519.go +++ b/crypto/ed25519/ed25519.go @@ -6,9 +6,9 @@ import ( "fmt" "io" - "github.com/tendermint/ed25519" - "github.com/tendermint/ed25519/extra25519" amino "github.com/tendermint/go-amino" + "golang.org/x/crypto/ed25519" // forked to github.com/tendermint/crypto + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/tmhash" ) @@ -47,8 +47,7 @@ func (privKey PrivKeyEd25519) Bytes() []byte { // Sign produces a signature on the provided message. func (privKey PrivKeyEd25519) Sign(msg []byte) ([]byte, error) { - privKeyBytes := [64]byte(privKey) - signatureBytes := ed25519.Sign(&privKeyBytes, msg) + signatureBytes := ed25519.Sign(privKey[:], msg) return signatureBytes[:], nil } @@ -65,14 +64,14 @@ func (privKey PrivKeyEd25519) PubKey() crypto.PubKey { break } } - if initialized { - var pubkeyBytes [PubKeyEd25519Size]byte - copy(pubkeyBytes[:], privKeyBytes[32:]) - return PubKeyEd25519(pubkeyBytes) + + if !initialized { + panic("Expected PrivKeyEd25519 to include concatenated pubkey bytes") } - pubBytes := *ed25519.MakePublicKey(&privKeyBytes) - return PubKeyEd25519(pubBytes) + var pubkeyBytes [PubKeyEd25519Size]byte + copy(pubkeyBytes[:], privKeyBytes[32:]) + return PubKeyEd25519(pubkeyBytes) } // Equals - you probably don't need to use this. @@ -85,17 +84,6 @@ func (privKey PrivKeyEd25519) Equals(other crypto.PrivKey) bool { } } -// ToCurve25519 takes a private key and returns its representation on -// Curve25519. Curve25519 is birationally equivalent to Edwards25519, -// which Ed25519 uses internally. This method is intended for use in -// an X25519 Diffie Hellman key exchange. -func (privKey PrivKeyEd25519) ToCurve25519() *[PubKeyEd25519Size]byte { - keyCurve25519 := new([32]byte) - privKeyBytes := [64]byte(privKey) - extra25519.PrivateKeyToCurve25519(keyCurve25519, &privKeyBytes) - return keyCurve25519 -} - // GenPrivKey generates a new ed25519 private key. // It uses OS randomness in conjunction with the current global random seed // in tendermint/libs/common to generate the private key. @@ -105,16 +93,16 @@ func GenPrivKey() PrivKeyEd25519 { // genPrivKey generates a new ed25519 private key using the provided reader. func genPrivKey(rand io.Reader) PrivKeyEd25519 { - privKey := new([64]byte) - _, err := io.ReadFull(rand, privKey[:32]) + seed := make([]byte, 32) + _, err := io.ReadFull(rand, seed[:]) if err != nil { panic(err) } - // ed25519.MakePublicKey(privKey) alters the last 32 bytes of privKey. - // It places the pubkey in the last 32 bytes of privKey, and returns the - // public key. - ed25519.MakePublicKey(privKey) - return PrivKeyEd25519(*privKey) + + privKey := ed25519.NewKeyFromSeed(seed) + var privKeyEd PrivKeyEd25519 + copy(privKeyEd[:], privKey) + return privKeyEd } // GenPrivKeyFromSecret hashes the secret with SHA2, and uses @@ -122,14 +110,12 @@ func genPrivKey(rand io.Reader) PrivKeyEd25519 { // NOTE: secret should be the output of a KDF like bcrypt, // if it's derived from user input. func GenPrivKeyFromSecret(secret []byte) PrivKeyEd25519 { - privKey32 := crypto.Sha256(secret) // Not Ripemd160 because we want 32 bytes. - privKey := new([64]byte) - copy(privKey[:32], privKey32) - // ed25519.MakePublicKey(privKey) alters the last 32 bytes of privKey. - // It places the pubkey in the last 32 bytes of privKey, and returns the - // public key. - ed25519.MakePublicKey(privKey) - return PrivKeyEd25519(*privKey) + seed := crypto.Sha256(secret) // Not Ripemd160 because we want 32 bytes. + + privKey := ed25519.NewKeyFromSeed(seed) + var privKeyEd PrivKeyEd25519 + copy(privKeyEd[:], privKey) + return privKeyEd } //------------------------------------- @@ -156,30 +142,12 @@ func (pubKey PubKeyEd25519) Bytes() []byte { return bz } -func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ []byte) bool { +func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig []byte) bool { // make sure we use the same algorithm to sign - if len(sig_) != SignatureSize { + if len(sig) != SignatureSize { return false } - sig := new([SignatureSize]byte) - copy(sig[:], sig_) - pubKeyBytes := [PubKeyEd25519Size]byte(pubKey) - return ed25519.Verify(&pubKeyBytes, msg, sig) -} - -// ToCurve25519 takes a public key and returns its representation on -// Curve25519. Curve25519 is birationally equivalent to Edwards25519, -// which Ed25519 uses internally. This method is intended for use in -// an X25519 Diffie Hellman key exchange. -// -// If there is an error, then this function returns nil. -func (pubKey PubKeyEd25519) ToCurve25519() *[PubKeyEd25519Size]byte { - keyCurve25519, pubKeyBytes := new([PubKeyEd25519Size]byte), [PubKeyEd25519Size]byte(pubKey) - ok := extra25519.PublicKeyToCurve25519(keyCurve25519, &pubKeyBytes) - if !ok { - return nil - } - return keyCurve25519 + return ed25519.Verify(pubKey[:], msg, sig) } func (pubKey PubKeyEd25519) String() string { diff --git a/crypto/hash.go b/crypto/hash.go index c1fb41f7a..a384bbb55 100644 --- a/crypto/hash.go +++ b/crypto/hash.go @@ -3,7 +3,7 @@ package crypto import ( "crypto/sha256" - "golang.org/x/crypto/ripemd160" + "golang.org/x/crypto/ripemd160" // forked to github.com/tendermint/crypto ) func Sha256(bytes []byte) []byte { diff --git a/crypto/secp256k1/secp256k1.go b/crypto/secp256k1/secp256k1.go index 2c64d1e9d..784409f3c 100644 --- a/crypto/secp256k1/secp256k1.go +++ b/crypto/secp256k1/secp256k1.go @@ -9,8 +9,9 @@ import ( secp256k1 "github.com/tendermint/btcd/btcec" amino "github.com/tendermint/go-amino" + "golang.org/x/crypto/ripemd160" // forked to github.com/tendermint/crypto + "github.com/tendermint/tendermint/crypto" - "golang.org/x/crypto/ripemd160" ) //------------------------------------- diff --git a/crypto/xchacha20poly1305/xchachapoly.go b/crypto/xchacha20poly1305/xchachapoly.go index c7a175b5f..115c9190f 100644 --- a/crypto/xchacha20poly1305/xchachapoly.go +++ b/crypto/xchacha20poly1305/xchachapoly.go @@ -8,7 +8,7 @@ import ( "errors" "fmt" - "golang.org/x/crypto/chacha20poly1305" + "golang.org/x/crypto/chacha20poly1305" // forked to github.com/tendermint/crypto ) // Implements crypto.AEAD diff --git a/crypto/xsalsa20symmetric/symmetric.go b/crypto/xsalsa20symmetric/symmetric.go index aa33ee14a..c51e24590 100644 --- a/crypto/xsalsa20symmetric/symmetric.go +++ b/crypto/xsalsa20symmetric/symmetric.go @@ -4,9 +4,10 @@ import ( "errors" "fmt" + "golang.org/x/crypto/nacl/secretbox" // forked to github.com/tendermint/crypto + "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tendermint/libs/common" - "golang.org/x/crypto/nacl/secretbox" ) // TODO, make this into a struct that implements crypto.Symmetric. diff --git a/crypto/xsalsa20symmetric/symmetric_test.go b/crypto/xsalsa20symmetric/symmetric_test.go index d955307ea..e9adf728e 100644 --- a/crypto/xsalsa20symmetric/symmetric_test.go +++ b/crypto/xsalsa20symmetric/symmetric_test.go @@ -6,8 +6,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/crypto/bcrypt" // forked to github.com/tendermint/crypto + "github.com/tendermint/tendermint/crypto" - "golang.org/x/crypto/bcrypt" ) func TestSimple(t *testing.T) { @@ -29,7 +30,9 @@ func TestSimpleWithKDF(t *testing.T) { plaintext := []byte("sometext") secretPass := []byte("somesecret") - secret, err := bcrypt.GenerateFromPassword(secretPass, 12) + salt := []byte("somesaltsomesalt") // len 16 + // NOTE: we use a fork of x/crypto so we can inject our own randomness for salt + secret, err := bcrypt.GenerateFromPassword(salt, secretPass, 12) if err != nil { t.Error(err) } diff --git a/p2p/conn/secret_connection.go b/p2p/conn/secret_connection.go index 3628eb4a3..acdd96de4 100644 --- a/p2p/conn/secret_connection.go +++ b/p2p/conn/secret_connection.go @@ -10,6 +10,7 @@ import ( "net" "time" + // forked to github.com/tendermint/crypto "golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/curve25519" "golang.org/x/crypto/nacl/box"