Use embedded lib key type in sdk pub keys instead of bytes. (#7672)
* Remove duplicate print message on keys add command (#7654) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * ed25519: use stdlib/crypto types * use standard package testing * use crypto/ed25519 instead of golang.org/x/crypto/ed25519 In Go 1.13 the new crypto/ed25519 package implements the Ed25519 signature scheme. This functionality was previously provided by the golang.org/x/crypto/ed25519 package, which becomes a wrapper for crypto/ed25519 when used with Go 1.13+. * use standard package testing for secp256k1 tests * secp256k1: add cross packages signature checks * ed25519: rollback the _test package name * rename underlyingSecp256k1 to btcSecp256k1 * package update Co-authored-by: Denis Fadeev <denis@fadeev.org> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
parent
426d195387
commit
bd9af94174
@ -1,6 +1,7 @@
|
||||
package ed25519
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/subtle"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -8,7 +9,6 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
tmed25519 "github.com/tendermint/tendermint/crypto/ed25519"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
@ -50,7 +50,7 @@ func (privKey *PrivKey) Bytes() []byte {
|
||||
// If these conditions aren't met, Sign will panic or produce an
|
||||
// incorrect signature.
|
||||
func (privKey *PrivKey) Sign(msg []byte) ([]byte, error) {
|
||||
return ed25519.Sign(ed25519.PrivateKey(privKey.Key), msg), nil
|
||||
return ed25519.Sign(privKey.Key, msg), nil
|
||||
}
|
||||
|
||||
// PubKey gets the corresponding public key from the private key.
|
||||
@ -171,7 +171,7 @@ func (pubKey *PubKey) VerifySignature(msg []byte, sig []byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
return ed25519.Verify(ed25519.PublicKey(pubKey.Key), msg, sig)
|
||||
return ed25519.Verify(pubKey.Key, msg, sig)
|
||||
}
|
||||
|
||||
func (pubKey *PubKey) String() string {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package ed25519_test
|
||||
|
||||
import (
|
||||
stded25519 "crypto/ed25519"
|
||||
"encoding/base64"
|
||||
"testing"
|
||||
|
||||
@ -11,7 +12,7 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto/sr25519"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
ed25519 "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
)
|
||||
|
||||
@ -19,17 +20,28 @@ func TestSignAndValidateEd25519(t *testing.T) {
|
||||
privKey := ed25519.GenPrivKey()
|
||||
pubKey := privKey.PubKey()
|
||||
|
||||
msg := crypto.CRandBytes(128)
|
||||
msg := crypto.CRandBytes(1000)
|
||||
sig, err := privKey.Sign(msg)
|
||||
require.Nil(t, err)
|
||||
|
||||
// Test the signature
|
||||
assert.True(t, pubKey.VerifySignature(msg, sig))
|
||||
|
||||
// ----
|
||||
// Test cross packages verification
|
||||
stdPrivKey := stded25519.PrivateKey(privKey.Key)
|
||||
stdPubKey := stdPrivKey.Public().(stded25519.PublicKey)
|
||||
|
||||
assert.Equal(t, stdPubKey, pubKey.(*ed25519.PubKey).Key)
|
||||
assert.Equal(t, stdPrivKey, privKey.Key)
|
||||
assert.True(t, stded25519.Verify(stdPubKey, msg, sig))
|
||||
sig2 := stded25519.Sign(stdPrivKey, msg)
|
||||
assert.True(t, pubKey.VerifySignature(msg, sig2))
|
||||
|
||||
// ----
|
||||
// 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.VerifySignature(msg, sig))
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
package ed25519
|
||||
|
||||
import (
|
||||
crypto_ed25519 "crypto/ed25519"
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
@ -29,7 +30,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
// the x-coordinate. Otherwise the first byte is a 0x03.
|
||||
// This prefix is followed with the x-coordinate.
|
||||
type PubKey struct {
|
||||
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
Key crypto_ed25519.PublicKey `protobuf:"bytes,1,opt,name=key,proto3,casttype=crypto/ed25519.PublicKey" json:"key,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PubKey) Reset() { *m = PubKey{} }
|
||||
@ -64,7 +65,7 @@ func (m *PubKey) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_PubKey proto.InternalMessageInfo
|
||||
|
||||
func (m *PubKey) GetKey() []byte {
|
||||
func (m *PubKey) GetKey() crypto_ed25519.PublicKey {
|
||||
if m != nil {
|
||||
return m.Key
|
||||
}
|
||||
@ -73,7 +74,7 @@ func (m *PubKey) GetKey() []byte {
|
||||
|
||||
// PrivKey defines a ed25519 private key.
|
||||
type PrivKey struct {
|
||||
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
Key crypto_ed25519.PrivateKey `protobuf:"bytes,1,opt,name=key,proto3,casttype=crypto/ed25519.PrivateKey" json:"key,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PrivKey) Reset() { *m = PrivKey{} }
|
||||
@ -109,7 +110,7 @@ func (m *PrivKey) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_PrivKey proto.InternalMessageInfo
|
||||
|
||||
func (m *PrivKey) GetKey() []byte {
|
||||
func (m *PrivKey) GetKey() crypto_ed25519.PrivateKey {
|
||||
if m != nil {
|
||||
return m.Key
|
||||
}
|
||||
@ -124,19 +125,21 @@ func init() {
|
||||
func init() { proto.RegisterFile("cosmos/crypto/ed25519/keys.proto", fileDescriptor_48fe3336771e732d) }
|
||||
|
||||
var fileDescriptor_48fe3336771e732d = []byte{
|
||||
// 183 bytes of a gzipped FileDescriptorProto
|
||||
// 221 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x48, 0xce, 0x2f, 0xce,
|
||||
0xcd, 0x2f, 0xd6, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0x4f, 0x4d, 0x31, 0x32, 0x35, 0x35,
|
||||
0xb4, 0xd4, 0xcf, 0x4e, 0xad, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x85, 0xa8,
|
||||
0xd0, 0x83, 0xa8, 0xd0, 0x83, 0xaa, 0x90, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xab, 0xd0, 0x07,
|
||||
0xb1, 0x20, 0x8a, 0x95, 0x14, 0xb8, 0xd8, 0x02, 0x4a, 0x93, 0xbc, 0x53, 0x2b, 0x85, 0x04, 0xb8,
|
||||
0x98, 0xb3, 0x53, 0x2b, 0x25, 0x18, 0x15, 0x18, 0x35, 0x78, 0x82, 0x40, 0x4c, 0x2b, 0x96, 0x19,
|
||||
0x0b, 0xe4, 0x19, 0x94, 0xa4, 0xb9, 0xd8, 0x03, 0x8a, 0x32, 0xcb, 0xb0, 0x2a, 0x71, 0xf2, 0x3a,
|
||||
0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63,
|
||||
0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0x83, 0xf4, 0xcc, 0x92, 0x8c, 0xd2,
|
||||
0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0x98, 0x93, 0xc1, 0x94, 0x6e, 0x71, 0x4a, 0x36, 0xcc, 0xf5,
|
||||
0x20, 0x57, 0xc3, 0xbc, 0x90, 0xc4, 0x06, 0x76, 0x91, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xcc,
|
||||
0xf3, 0x11, 0x99, 0xe2, 0x00, 0x00, 0x00,
|
||||
0xb1, 0x20, 0x8a, 0x95, 0xec, 0xb8, 0xd8, 0x02, 0x4a, 0x93, 0xbc, 0x53, 0x2b, 0x85, 0xf4, 0xb8,
|
||||
0x98, 0xb3, 0x53, 0x2b, 0x25, 0x18, 0x15, 0x18, 0x35, 0x78, 0x9c, 0x64, 0x7e, 0xdd, 0x93, 0x97,
|
||||
0x40, 0xb5, 0x42, 0x2f, 0xa0, 0x34, 0x29, 0x27, 0x33, 0xd9, 0x3b, 0xb5, 0x32, 0x08, 0xa4, 0xd0,
|
||||
0x8a, 0x65, 0xc6, 0x02, 0x79, 0x06, 0x25, 0x2b, 0x2e, 0xf6, 0x80, 0xa2, 0xcc, 0x32, 0x90, 0x01,
|
||||
0xfa, 0xc8, 0x06, 0xc8, 0xfe, 0xba, 0x27, 0x2f, 0x89, 0x6e, 0x40, 0x51, 0x66, 0x59, 0x62, 0x49,
|
||||
0x2a, 0xcc, 0x04, 0x27, 0xaf, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48,
|
||||
0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0x32,
|
||||
0x48, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x87, 0xf9, 0x17, 0x4c, 0xe9,
|
||||
0x16, 0xa7, 0x64, 0xc3, 0xbc, 0x0e, 0xf2, 0x32, 0xcc, 0xec, 0x24, 0x36, 0xb0, 0x77, 0x8c, 0x01,
|
||||
0x01, 0x00, 0x00, 0xff, 0xff, 0xb0, 0xd8, 0x01, 0xc0, 0x1f, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *PubKey) Marshal() (dAtA []byte, err error) {
|
||||
|
||||
@ -9,13 +9,12 @@ import (
|
||||
"math/big"
|
||||
|
||||
secp256k1 "github.com/btcsuite/btcd/btcec"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"golang.org/x/crypto/ripemd160" // nolint: staticcheck // necessary for Bitcoin address format
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
)
|
||||
|
||||
var _ cryptotypes.PrivKey = &PrivKey{}
|
||||
|
||||
@ -19,6 +19,8 @@ func (privKey *PrivKey) Sign(msg []byte) ([]byte, error) {
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
// VerifySignature validates the signature.
|
||||
// The msg will be hashed prior to signature verification.
|
||||
func (pubKey *PrivKey) VerifySignature(msg []byte, sig []byte) bool {
|
||||
return secp256k1.VerifySignature(pubKey.Key, crypto.Sha256(msg), sig)
|
||||
}
|
||||
|
||||
@ -5,9 +5,8 @@ import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
btcSecp256k1 "github.com/btcsuite/btcd/btcec"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
underlyingSecp256k1 "github.com/btcsuite/btcd/btcec"
|
||||
)
|
||||
|
||||
func Test_genPrivKey(t *testing.T) {
|
||||
@ -25,7 +24,7 @@ func Test_genPrivKey(t *testing.T) {
|
||||
shouldPanic bool
|
||||
}{
|
||||
{"empty bytes (panics because 1st 32 bytes are zero and 0 is not a valid field element)", empty, true},
|
||||
{"curve order: N", underlyingSecp256k1.S256().N.Bytes(), true},
|
||||
{"curve order: N", btcSecp256k1.S256().N.Bytes(), true},
|
||||
{"valid because 0 < 1 < N", validOne, false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
@ -39,7 +38,7 @@ func Test_genPrivKey(t *testing.T) {
|
||||
}
|
||||
got := genPrivKey(bytes.NewReader(tt.notSoRand))
|
||||
fe := new(big.Int).SetBytes(got[:])
|
||||
require.True(t, fe.Cmp(underlyingSecp256k1.S256().N) < 0)
|
||||
require.True(t, fe.Cmp(btcSecp256k1.S256().N) < 0)
|
||||
require.True(t, fe.Sign() > 0)
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,20 +1,19 @@
|
||||
package secp256k1_test
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
btcSecp256k1 "github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcutil/base58"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/sr25519"
|
||||
|
||||
underlyingSecp256k1 "github.com/btcsuite/btcd/btcec"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
@ -41,7 +40,7 @@ func TestPubKeySecp256k1Address(t *testing.T) {
|
||||
addrBbz, _, _ := base58.CheckDecode(d.addr)
|
||||
addrB := crypto.Address(addrBbz)
|
||||
|
||||
var priv secp256k1.PrivKey = secp256k1.PrivKey{Key: privB}
|
||||
var priv = secp256k1.PrivKey{Key: privB}
|
||||
|
||||
pubKey := priv.PubKey()
|
||||
pubT, _ := pubKey.(*secp256k1.PubKey)
|
||||
@ -56,15 +55,34 @@ func TestSignAndValidateSecp256k1(t *testing.T) {
|
||||
privKey := secp256k1.GenPrivKey()
|
||||
pubKey := privKey.PubKey()
|
||||
|
||||
msg := crypto.CRandBytes(128)
|
||||
msg := crypto.CRandBytes(1000)
|
||||
sig, err := privKey.Sign(msg)
|
||||
require.Nil(t, err)
|
||||
|
||||
assert.True(t, pubKey.VerifySignature(msg, sig))
|
||||
|
||||
// ----
|
||||
// Test cross packages verification
|
||||
msgHash := crypto.Sha256(msg)
|
||||
btcPrivKey, btcPubKey := btcSecp256k1.PrivKeyFromBytes(btcSecp256k1.S256(), privKey.Key)
|
||||
// This fails: malformed signature: no header magic
|
||||
// btcSig, err := secp256k1.ParseSignature(sig, secp256k1.S256())
|
||||
// require.NoError(t, err)
|
||||
// assert.True(t, btcSig.Verify(msgHash, btcPubKey))
|
||||
// So we do a hacky way:
|
||||
r := new(big.Int)
|
||||
s := new(big.Int)
|
||||
r.SetBytes(sig[:32])
|
||||
s.SetBytes(sig[32:])
|
||||
ok := ecdsa.Verify(btcPubKey.ToECDSA(), msgHash, r, s)
|
||||
require.True(t, ok)
|
||||
|
||||
sig2, err := btcPrivKey.Sign(msgHash)
|
||||
require.NoError(t, err)
|
||||
pubKey.VerifySignature(msg, sig2.Serialize())
|
||||
|
||||
// ----
|
||||
// Mutate the signature, just one bit.
|
||||
sig[3] ^= byte(0x01)
|
||||
|
||||
assert.False(t, pubKey.VerifySignature(msg, sig))
|
||||
}
|
||||
|
||||
@ -79,7 +97,7 @@ func TestSecp256k1LoadPrivkeyAndSerializeIsIdentity(t *testing.T) {
|
||||
|
||||
// This function creates a private and public key in the underlying libraries format.
|
||||
// The private key is basically calling new(big.Int).SetBytes(pk), which removes leading zero bytes
|
||||
priv, _ := underlyingSecp256k1.PrivKeyFromBytes(underlyingSecp256k1.S256(), privKeyBytes[:])
|
||||
priv, _ := btcSecp256k1.PrivKeyFromBytes(btcSecp256k1.S256(), privKeyBytes[:])
|
||||
// this takes the bytes returned by `(big int).Bytes()`, and if the length is less than 32 bytes,
|
||||
// pads the bytes from the left with zero bytes. Therefore these two functions composed
|
||||
// result in the identity function on privKeyBytes, hence the following equality check
|
||||
@ -91,7 +109,7 @@ func TestSecp256k1LoadPrivkeyAndSerializeIsIdentity(t *testing.T) {
|
||||
|
||||
func TestGenPrivKeyFromSecret(t *testing.T) {
|
||||
// curve oder N
|
||||
N := underlyingSecp256k1.S256().N
|
||||
N := btcSecp256k1.S256().N
|
||||
tests := []struct {
|
||||
name string
|
||||
secret []byte
|
||||
|
||||
@ -13,10 +13,10 @@ option go_package = "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519";
|
||||
message PubKey {
|
||||
option (gogoproto.goproto_stringer) = false;
|
||||
|
||||
bytes key = 1;
|
||||
bytes key = 1 [(gogoproto.casttype) = "crypto/ed25519.PublicKey"];
|
||||
}
|
||||
|
||||
// PrivKey defines a ed25519 private key.
|
||||
message PrivKey {
|
||||
bytes key = 1;
|
||||
bytes key = 1 [(gogoproto.casttype) = "crypto/ed25519.PrivateKey"];
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user