diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 6e8beed4b..d031baa26 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -98,6 +98,7 @@ program](https://hackerone.com/tendermint). - [p2p] [\#4185](https://github.com/tendermint/tendermint/pull/4185) Simplify `SecretConnection` handshake with merlin - [cli] [\#4065](https://github.com/tendermint/tendermint/issues/4065) Add `--consensus.create_empty_blocks_interval` flag (@jgimeno) - [docs] [\#4065](https://github.com/tendermint/tendermint/issues/4065) Document `--consensus.create_empty_blocks_interval` flag (@jgimeno) +- [crypto] [\#4190](https://github.com/tendermint/tendermint/pull/4190) Added SR25519 signature scheme ### BUG FIXES: diff --git a/crypto/README.md b/crypto/README.md index a77a7ab6c..18a400a0f 100644 --- a/crypto/README.md +++ b/crypto/README.md @@ -23,8 +23,10 @@ crypto `.Bytes()` uses Amino:binary encoding, but Amino:JSON is also supported. ```go Example Amino:JSON encodings: -ed25519.PrivKeyEd25519 - {"type":"954568A3288910","value":"EVkqJO/jIXp3rkASXfh9YnyToYXRXhBr6g9cQVxPFnQBP/5povV4HTjvsy530kybxKHwEi85iU8YL0qQhSYVoQ=="} -ed25519.PubKeyEd25519 - {"type":"AC26791624DE60","value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE="} -crypto.PrivKeySecp256k1 - {"type":"019E82E1B0F798","value":"zx4Pnh67N+g2V+5vZbQzEyRerX9c4ccNZOVzM9RvJ0Y="} -crypto.PubKeySecp256k1 - {"type":"F8CCEAEB5AE980","value":"A8lPKJXcNl5VHt1FK8a244K9EJuS4WX1hFBnwisi0IJx"} +ed25519.PrivKeyEd25519 - {"type":"tendermint/PrivKeyEd25519","value":"EVkqJO/jIXp3rkASXfh9YnyToYXRXhBr6g9cQVxPFnQBP/5povV4HTjvsy530kybxKHwEi85iU8YL0qQhSYVoQ=="} +ed25519.PubKeyEd25519 - {"type":"tendermint/PubKeyEd25519","value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE="} +sr25519.PrivKeySr25519 - {"type":"tendermint/PrivKeySr25519","value":"xtYVH8UCIqfrY8FIFc0QEpAEBShSG4NT0zlEOVSZ2w4="} +sr25519.PubKeySr25519 - {"type":"tendermint/PubKeySr25519","value":"8sKBLKQ/OoXMcAJVxBqz1U7TyxRFQ5cmliuHy4MrF0s="} +crypto.PrivKeySecp256k1 - {"type":"tendermint/PrivKeySecp256k1","value":"zx4Pnh67N+g2V+5vZbQzEyRerX9c4ccNZOVzM9RvJ0Y="} +crypto.PubKeySecp256k1 - {"type":"tendermint/PubKeySecp256k1","value":"A8lPKJXcNl5VHt1FK8a244K9EJuS4WX1hFBnwisi0IJx"} ``` diff --git a/crypto/encoding/amino/amino.go b/crypto/encoding/amino/amino.go index fc2236aae..b63eb738d 100644 --- a/crypto/encoding/amino/amino.go +++ b/crypto/encoding/amino/amino.go @@ -8,6 +8,7 @@ import ( "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/multisig" "github.com/tendermint/tendermint/crypto/secp256k1" + "github.com/tendermint/tendermint/crypto/sr25519" ) var cdc = amino.NewCodec() @@ -30,6 +31,7 @@ func init() { // TODO: Have amino provide a way to go from concrete struct to route directly. // Its currently a private API nameTable[reflect.TypeOf(ed25519.PubKeyEd25519{})] = ed25519.PubKeyAminoName + nameTable[reflect.TypeOf(sr25519.PubKeySr25519{})] = sr25519.PubKeyAminoName nameTable[reflect.TypeOf(secp256k1.PubKeySecp256k1{})] = secp256k1.PubKeyAminoName nameTable[reflect.TypeOf(multisig.PubKeyMultisigThreshold{})] = multisig.PubKeyMultisigThresholdAminoRoute } @@ -48,6 +50,8 @@ func RegisterAmino(cdc *amino.Codec) { cdc.RegisterInterface((*crypto.PubKey)(nil), nil) cdc.RegisterConcrete(ed25519.PubKeyEd25519{}, ed25519.PubKeyAminoName, nil) + cdc.RegisterConcrete(sr25519.PubKeySr25519{}, + sr25519.PubKeyAminoName, nil) cdc.RegisterConcrete(secp256k1.PubKeySecp256k1{}, secp256k1.PubKeyAminoName, nil) cdc.RegisterConcrete(multisig.PubKeyMultisigThreshold{}, @@ -56,6 +60,8 @@ func RegisterAmino(cdc *amino.Codec) { cdc.RegisterInterface((*crypto.PrivKey)(nil), nil) cdc.RegisterConcrete(ed25519.PrivKeyEd25519{}, ed25519.PrivKeyAminoName, nil) + cdc.RegisterConcrete(sr25519.PrivKeySr25519{}, + sr25519.PrivKeyAminoName, nil) cdc.RegisterConcrete(secp256k1.PrivKeySecp256k1{}, secp256k1.PrivKeyAminoName, nil) } diff --git a/crypto/encoding/amino/encode_test.go b/crypto/encoding/amino/encode_test.go index c3d8f2676..67a7566dd 100644 --- a/crypto/encoding/amino/encode_test.go +++ b/crypto/encoding/amino/encode_test.go @@ -13,6 +13,7 @@ import ( "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/multisig" "github.com/tendermint/tendermint/crypto/secp256k1" + "github.com/tendermint/tendermint/crypto/sr25519" ) type byter interface { @@ -57,9 +58,11 @@ func ExamplePrintRegisteredTypes() { // Output: | Type | Name | Prefix | Length | Notes | //| ---- | ---- | ------ | ----- | ------ | //| PubKeyEd25519 | tendermint/PubKeyEd25519 | 0x1624DE64 | 0x20 | | + //| PubKeySr25519 | tendermint/PubKeySr25519 | 0x0DFB1005 | 0x20 | | //| PubKeySecp256k1 | tendermint/PubKeySecp256k1 | 0xEB5AE987 | 0x21 | | //| PubKeyMultisigThreshold | tendermint/PubKeyMultisigThreshold | 0x22C1F7E2 | variable | | //| PrivKeyEd25519 | tendermint/PrivKeyEd25519 | 0xA3288910 | 0x40 | | + //| PrivKeySr25519 | tendermint/PrivKeySr25519 | 0x2F82D78B | 0x20 | | //| PrivKeySecp256k1 | tendermint/PrivKeySecp256k1 | 0xE1B0F79B | 0x20 | | } @@ -74,6 +77,12 @@ func TestKeyEncodings(t *testing.T) { pubSize: 37, sigSize: 65, }, + { + privKey: sr25519.GenPrivKey(), + privSize: 37, + pubSize: 37, + sigSize: 65, + }, { privKey: secp256k1.GenPrivKey(), privSize: 37, @@ -139,6 +148,7 @@ func TestPubkeyAminoName(t *testing.T) { found bool }{ {ed25519.PubKeyEd25519{}, ed25519.PubKeyAminoName, true}, + {sr25519.PubKeySr25519{}, sr25519.PubKeyAminoName, true}, {secp256k1.PubKeySecp256k1{}, secp256k1.PubKeyAminoName, true}, {multisig.PubKeyMultisigThreshold{}, multisig.PubKeyMultisigThresholdAminoRoute, true}, } @@ -219,6 +229,7 @@ func TestRegisterKeyType(t *testing.T) { nameTable = make(map[reflect.Type]string, 3) RegisterAmino(cdc) nameTable[reflect.TypeOf(ed25519.PubKeyEd25519{})] = ed25519.PubKeyAminoName + nameTable[reflect.TypeOf(sr25519.PubKeySr25519{})] = sr25519.PubKeyAminoName nameTable[reflect.TypeOf(secp256k1.PubKeySecp256k1{})] = secp256k1.PubKeyAminoName nameTable[reflect.TypeOf(multisig.PubKeyMultisigThreshold{})] = multisig.PubKeyMultisigThresholdAminoRoute } diff --git a/crypto/sr25519/bench_test.go b/crypto/sr25519/bench_test.go new file mode 100644 index 000000000..0561eff72 --- /dev/null +++ b/crypto/sr25519/bench_test.go @@ -0,0 +1,26 @@ +package sr25519 + +import ( + "io" + "testing" + + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/internal/benchmarking" +) + +func BenchmarkKeyGeneration(b *testing.B) { + benchmarkKeygenWrapper := func(reader io.Reader) crypto.PrivKey { + return genPrivKey(reader) + } + benchmarking.BenchmarkKeyGeneration(b, benchmarkKeygenWrapper) +} + +func BenchmarkSigning(b *testing.B) { + priv := GenPrivKey() + benchmarking.BenchmarkSigning(b, priv) +} + +func BenchmarkVerification(b *testing.B) { + priv := GenPrivKey() + benchmarking.BenchmarkVerification(b, priv) +} diff --git a/crypto/sr25519/codec.go b/crypto/sr25519/codec.go new file mode 100644 index 000000000..c3e6bd646 --- /dev/null +++ b/crypto/sr25519/codec.go @@ -0,0 +1,29 @@ +package sr25519 + +import ( + amino "github.com/tendermint/go-amino" + "github.com/tendermint/tendermint/crypto" +) + +var _ crypto.PrivKey = PrivKeySr25519{} + +const ( + PrivKeyAminoName = "tendermint/PrivKeySr25519" + PubKeyAminoName = "tendermint/PubKeySr25519" + + // SignatureSize is the size of an Edwards25519 signature. Namely the size of a compressed + // Sr25519 point, and a field element. Both of which are 32 bytes. + SignatureSize = 64 +) + +var cdc = amino.NewCodec() + +func init() { + cdc.RegisterInterface((*crypto.PubKey)(nil), nil) + cdc.RegisterConcrete(PubKeySr25519{}, + PubKeyAminoName, nil) + + cdc.RegisterInterface((*crypto.PrivKey)(nil), nil) + cdc.RegisterConcrete(PrivKeySr25519{}, + PrivKeyAminoName, nil) +} diff --git a/crypto/sr25519/privkey.go b/crypto/sr25519/privkey.go new file mode 100644 index 000000000..930c6bdc2 --- /dev/null +++ b/crypto/sr25519/privkey.go @@ -0,0 +1,99 @@ +package sr25519 + +import ( + "crypto/subtle" + "fmt" + "io" + + "github.com/tendermint/tendermint/crypto" + + schnorrkel "github.com/ChainSafe/go-schnorrkel" +) + +// PrivKeySr25519Size is the number of bytes in an Sr25519 private key. +const PrivKeySr25519Size = 32 + +// PrivKeySr25519 implements crypto.PrivKey. +type PrivKeySr25519 [PrivKeySr25519Size]byte + +// Bytes marshals the privkey using amino encoding. +func (privKey PrivKeySr25519) Bytes() []byte { + return cdc.MustMarshalBinaryBare(privKey) +} + +// Sign produces a signature on the provided message. +func (privKey PrivKeySr25519) Sign(msg []byte) ([]byte, error) { + secretKey := &(schnorrkel.SecretKey{}) + err := secretKey.Decode(privKey) + if err != nil { + return []byte{}, err + } + + signingContext := schnorrkel.NewSigningContext([]byte{}, msg) + + sig, err := secretKey.Sign(signingContext) + if err != nil { + return []byte{}, err + } + + sigBytes := sig.Encode() + return sigBytes[:], nil +} + +// PubKey gets the corresponding public key from the private key. +func (privKey PrivKeySr25519) PubKey() crypto.PubKey { + + secretKey := &(schnorrkel.SecretKey{}) + err := secretKey.Decode(privKey) + if err != nil { + panic(fmt.Sprintf("Invalid private key: %v", err)) + } + + pubkey, _ := secretKey.Public() + + return PubKeySr25519(pubkey.Encode()) +} + +// Equals - you probably don't need to use this. +// Runs in constant time based on length of the keys. +func (privKey PrivKeySr25519) Equals(other crypto.PrivKey) bool { + if otherEd, ok := other.(PrivKeySr25519); ok { + return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 1 + } else { + return false + } +} + +// GenPrivKey generates a new sr25519 private key. +// It uses OS randomness in conjunction with the current global random seed +// in tendermint/libs/common to generate the private key. +func GenPrivKey() PrivKeySr25519 { + return genPrivKey(crypto.CReader()) +} + +// genPrivKey generates a new sr25519 private key using the provided reader. +func genPrivKey(rand io.Reader) PrivKeySr25519 { + var seed [64]byte + + out := make([]byte, 64) + _, err := io.ReadFull(rand, out) + if err != nil { + panic(err) + } + + copy(seed[:], out) + + return schnorrkel.NewMiniSecretKey(seed).ExpandEd25519().Encode() +} + +// GenPrivKeyFromSecret hashes the secret with SHA2, and uses +// that 32 byte output to create the private key. +// NOTE: secret should be the output of a KDF like bcrypt, +// if it's derived from user input. +func GenPrivKeyFromSecret(secret []byte) PrivKeySr25519 { + seed := crypto.Sha256(secret) // Not Ripemd160 because we want 32 bytes. + var bz [PrivKeySr25519Size]byte + copy(bz[:], seed) + privKey, _ := schnorrkel.NewMiniSecretKeyFromRaw(bz) + return privKey.ExpandEd25519().Encode() +} diff --git a/crypto/sr25519/pubkey.go b/crypto/sr25519/pubkey.go new file mode 100644 index 000000000..bb9722431 --- /dev/null +++ b/crypto/sr25519/pubkey.go @@ -0,0 +1,72 @@ +package sr25519 + +import ( + "bytes" + "fmt" + + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/tmhash" + + schnorrkel "github.com/ChainSafe/go-schnorrkel" +) + +var _ crypto.PubKey = PubKeySr25519{} + +// PubKeySr25519Size is the number of bytes in an Sr25519 public key. +const PubKeySr25519Size = 32 + +// PubKeySr25519 implements crypto.PubKey for the Sr25519 signature scheme. +type PubKeySr25519 [PubKeySr25519Size]byte + +// Address is the SHA256-20 of the raw pubkey bytes. +func (pubKey PubKeySr25519) Address() crypto.Address { + return crypto.Address(tmhash.SumTruncated(pubKey[:])) +} + +// Bytes marshals the PubKey using amino encoding. +func (pubKey PubKeySr25519) Bytes() []byte { + bz, err := cdc.MarshalBinaryBare(pubKey) + if err != nil { + panic(err) + } + return bz +} + +func (pubKey PubKeySr25519) VerifyBytes(msg []byte, sig []byte) bool { + // make sure we use the same algorithm to sign + if len(sig) != SignatureSize { + return false + } + var sig64 [SignatureSize]byte + copy(sig64[:], sig) + + publicKey := &(schnorrkel.PublicKey{}) + err := publicKey.Decode(pubKey) + if err != nil { + return false + } + + signingContext := schnorrkel.NewSigningContext([]byte{}, msg) + + signature := &(schnorrkel.Signature{}) + err = signature.Decode(sig64) + if err != nil { + return false + } + + return publicKey.Verify(signature, signingContext) +} + +func (pubKey PubKeySr25519) String() string { + return fmt.Sprintf("PubKeySr25519{%X}", pubKey[:]) +} + +// Equals - checks that two public keys are the same time +// Runs in constant time based on length of the keys. +func (pubKey PubKeySr25519) Equals(other crypto.PubKey) bool { + if otherEd, ok := other.(PubKeySr25519); ok { + return bytes.Equal(pubKey[:], otherEd[:]) + } else { + return false + } +} diff --git a/crypto/sr25519/sr25519_test.go b/crypto/sr25519/sr25519_test.go new file mode 100644 index 000000000..62cf564a9 --- /dev/null +++ b/crypto/sr25519/sr25519_test.go @@ -0,0 +1,31 @@ +package sr25519_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/sr25519" +) + +func TestSignAndValidateSr25519(t *testing.T) { + + privKey := sr25519.GenPrivKey() + pubKey := privKey.PubKey() + + msg := crypto.CRandBytes(128) + sig, err := privKey.Sign(msg) + require.Nil(t, err) + + // Test the signature + assert.True(t, pubKey.VerifyBytes(msg, sig)) + assert.True(t, pubKey.VerifyBytes(msg, sig)) + + // Mutate the signature, just one bit. + // TODO: Replace this with a much better fuzzer, tendermint/ed25519/issues/10 + sig[7] ^= byte(0x01) + + assert.False(t, pubKey.VerifyBytes(msg, sig)) +} diff --git a/go.mod b/go.mod index d0875f578..1ea29459a 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/tendermint/tendermint go 1.12 require ( + github.com/ChainSafe/go-schnorrkel v0.0.0-20191204112926-74e22bf42a85 github.com/VividCortex/gohistogram v1.0.0 // indirect github.com/Workiva/go-datastructures v1.0.50 github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d @@ -18,6 +19,7 @@ require ( github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/libp2p/go-buffer-pool v0.0.2 github.com/magiconair/properties v1.8.1 + github.com/mitchellh/gox v1.0.1 // indirect github.com/pkg/errors v0.8.1 github.com/prometheus/client_golang v0.9.3 github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165 @@ -25,6 +27,7 @@ require ( github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa github.com/spf13/cobra v0.0.1 github.com/spf13/viper v1.5.0 + github.com/square/certstrap v1.2.0 // indirect github.com/stretchr/testify v1.4.0 github.com/stumble/gorocksdb v0.0.3 // indirect github.com/tendermint/go-amino v0.14.1 diff --git a/go.sum b/go.sum index bf36c3206..1c69ef52d 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/ChainSafe/go-schnorrkel v0.0.0-20191119190741-a5524ad9568e h1:rkK/bP+ZPCAygCa5ko4S1lxUynjkJAN08SL8Wq6HRfM= +github.com/ChainSafe/go-schnorrkel v0.0.0-20191119190741-a5524ad9568e/go.mod h1:+soe5c7df0vttdVAmHHSAenpDToZsECJR8psL1P/7Bg= +github.com/ChainSafe/go-schnorrkel v0.0.0-20191204112926-74e22bf42a85 h1:cAkGY6Gq3Lpt9H+BE1kipBnUrRgcgLSfYjOVxdJJdV8= +github.com/ChainSafe/go-schnorrkel v0.0.0-20191204112926-74e22bf42a85/go.mod h1:XghbtLKucwsjjP+kApu/dx0Zkbb4tB8nzI8hnwtYc34= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= @@ -90,8 +94,16 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f h1:8N8XWLZelZNibkhM1FuF+3Ad3YIbgirjdMiVA0eUkaM= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/ristretto255 v0.1.0 h1:WQKpyRsq8Yt7dm0oq6Gj18BGku/Zbj/TOIolBYfmbiI= +github.com/gtank/ristretto255 v0.1.0/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= +github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= +github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= +github.com/hashicorp/go-version v1.0.0 h1:21MVWPKDphxa7ineQQTrCU5brh7OuVVAzGOCnnCPtE8= +github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c h1:kQWxfPIHVLbgLzphqk3QUflDy9QdksZR4ygR807bpy0= +github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= @@ -122,6 +134,10 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/mitchellh/gox v1.0.1 h1:x0jD3dcHk9a9xPSDN6YEL4xL6Qz0dvNYm8yZqui5chI= +github.com/mitchellh/gox v1.0.1/go.mod h1:ED6BioOGXMswlXa2zxfh/xdd5QhwYliBFn9V18Ap4z4= +github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -178,6 +194,8 @@ github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.5.0 h1:GpsTwfsQ27oS/Aha/6d1oD7tpKIqWnOA6tgOX9HHkt4= github.com/spf13/viper v1.5.0/go.mod h1:AkYRkVJF8TkSG/xet6PzXX+l39KhhXa2pdqVSxnTcn4= +github.com/square/certstrap v1.2.0 h1:ecgyABrbFLr8jSbOC6oTBmBek0t/HqtgrMUZCPuyfdw= +github.com/square/certstrap v1.2.0/go.mod h1:CUHqV+fxJW0Y5UQFnnbYwQ7bpKXO1AKbic9g73799yw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -206,6 +224,8 @@ github.com/tendermint/tm-db v0.3.0 h1:txK8j+sdY+Ml9VfkxU0jW2VUAygKdoODQBS+kTYlWl github.com/tendermint/tm-db v0.3.0/go.mod h1:ZpwA9nGbXwQDyMsIneHgbP4Q1SbPXPdFd9uMzUKLPsU= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/urfave/cli v1.21.0 h1:wYSSj06510qPIzGSua9ZqsncMmWE3Zr55KBERygyrxE= +github.com/urfave/cli v1.21.0/go.mod h1:lxDj6qX9Q6lWQxIrbrT0nwecwUtRnhVZAJjJZrVUZZQ= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -216,6 +236,7 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -244,6 +265,7 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= diff --git a/types/protobuf.go b/types/protobuf.go index 3ca521a4f..dcf84600f 100644 --- a/types/protobuf.go +++ b/types/protobuf.go @@ -9,6 +9,7 @@ import ( "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/secp256k1" + "github.com/tendermint/tendermint/crypto/sr25519" ) //------------------------------------------------------- @@ -21,12 +22,14 @@ const ( const ( ABCIPubKeyTypeEd25519 = "ed25519" + ABCIPubKeyTypeSr25519 = "sr25519" ABCIPubKeyTypeSecp256k1 = "secp256k1" ) // TODO: Make non-global by allowing for registration of more pubkey types var ABCIPubKeyTypesToAminoNames = map[string]string{ ABCIPubKeyTypeEd25519: ed25519.PubKeyAminoName, + ABCIPubKeyTypeSr25519: sr25519.PubKeyAminoName, ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyAminoName, } @@ -102,6 +105,11 @@ func (tm2pb) PubKey(pubKey crypto.PubKey) abci.PubKey { Type: ABCIPubKeyTypeEd25519, Data: pk[:], } + case sr25519.PubKeySr25519: + return abci.PubKey{ + Type: ABCIPubKeyTypeSr25519, + Data: pk[:], + } case secp256k1.PubKeySecp256k1: return abci.PubKey{ Type: ABCIPubKeyTypeSecp256k1, @@ -194,6 +202,14 @@ func (pb2tm) PubKey(pubKey abci.PubKey) (crypto.PubKey, error) { var pk ed25519.PubKeyEd25519 copy(pk[:], pubKey.Data) return pk, nil + case ABCIPubKeyTypeSr25519: + if len(pubKey.Data) != sr25519.PubKeySr25519Size { + return nil, fmt.Errorf("invalid size for PubKeySr25519. Got %d, expected %d", + len(pubKey.Data), sr25519.PubKeySr25519Size) + } + var pk sr25519.PubKeySr25519 + copy(pk[:], pubKey.Data) + return pk, nil case ABCIPubKeyTypeSecp256k1: if len(pubKey.Data) != secp256k1.PubKeySecp256k1Size { return nil, fmt.Errorf("invalid size for PubKeySecp256k1. Got %d, expected %d",