keys: change to []bytes (#4950)

This commit is contained in:
Marko
2020-06-04 15:32:42 +02:00
committed by GitHub
parent d53a8d0377
commit 7c576f02ab
21 changed files with 152 additions and 160 deletions

View File

@@ -6,7 +6,6 @@ import (
"fmt"
"io"
amino "github.com/tendermint/go-amino"
"golang.org/x/crypto/ed25519"
"github.com/tendermint/tendermint/crypto"
@@ -20,29 +19,24 @@ var _ crypto.PrivKey = PrivKey{}
const (
PrivKeyAminoName = "tendermint/PrivKeyEd25519"
PubKeyAminoName = "tendermint/PubKeyEd25519"
// PubKeySize is is the size, in bytes, of public keys as used in this package.
PubKeySize = 32
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
PrivateKeySize = 64
// Size of an Edwards25519 signature. Namely the size of a compressed
// Edwards25519 point, and a field element. Both of which are 32 bytes.
SignatureSize = 64
// SeedSize is the size, in bytes, of private key seeds. These are the
// private key representations used by RFC 8032.
SeedSize = 32
)
var cdc = amino.NewCodec()
func init() {
cdc.RegisterInterface((*crypto.PubKey)(nil), nil)
cdc.RegisterConcrete(PubKey{},
PubKeyAminoName, nil)
cdc.RegisterInterface((*crypto.PrivKey)(nil), nil)
cdc.RegisterConcrete(PrivKey{},
PrivKeyAminoName, nil)
}
// PrivKey implements crypto.PrivKey.
type PrivKey [64]byte
type PrivKey []byte
// Bytes marshals the privkey using amino encoding.
// Bytes returns the privkey byte format.
func (privKey PrivKey) Bytes() []byte {
return cdc.MustMarshalBinaryBare(privKey)
return []byte(privKey)
}
// Sign produces a signature on the provided message.
@@ -53,18 +47,18 @@ 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) {
signatureBytes := ed25519.Sign(privKey[:], msg)
signatureBytes := ed25519.Sign(ed25519.PrivateKey(privKey), msg)
return signatureBytes, nil
}
// PubKey gets the corresponding public key from the private key.
//
// Panics if the private key is not initialized.
func (privKey PrivKey) PubKey() crypto.PubKey {
privKeyBytes := [64]byte(privKey)
// If the latter 32 bytes of the privkey are all zero, privkey is not
// initialized.
initialized := false
// If the latter 32 bytes of the privkey are all zero, compute the pubkey
// otherwise privkey is initialized and we can use the cached value inside
// of the private key.
for _, v := range privKeyBytes[32:] {
for _, v := range privKey[32:] {
if v != 0 {
initialized = true
break
@@ -75,8 +69,8 @@ func (privKey PrivKey) PubKey() crypto.PubKey {
panic("Expected ed25519 PrivKey to include concatenated pubkey bytes")
}
var pubkeyBytes [PubKeySize]byte
copy(pubkeyBytes[:], privKeyBytes[32:])
pubkeyBytes := make([]byte, PubKeySize)
copy(pubkeyBytes, privKey[32:])
return PubKey(pubkeyBytes)
}
@@ -99,16 +93,14 @@ func GenPrivKey() PrivKey {
// genPrivKey generates a new ed25519 private key using the provided reader.
func genPrivKey(rand io.Reader) PrivKey {
seed := make([]byte, 32)
seed := make([]byte, SeedSize)
_, err := io.ReadFull(rand, seed)
if err != nil {
panic(err)
}
privKey := ed25519.NewKeyFromSeed(seed)
var privKeyEd PrivKey
copy(privKeyEd[:], privKey)
return privKeyEd
return PrivKey(ed25519.NewKeyFromSeed(seed))
}
// GenPrivKeyFromSecret hashes the secret with SHA2, and uses
@@ -118,34 +110,27 @@ func genPrivKey(rand io.Reader) PrivKey {
func GenPrivKeyFromSecret(secret []byte) PrivKey {
seed := crypto.Sha256(secret) // Not Ripemd160 because we want 32 bytes.
privKey := ed25519.NewKeyFromSeed(seed)
var privKeyEd PrivKey
copy(privKeyEd[:], privKey)
return privKeyEd
return PrivKey(ed25519.NewKeyFromSeed(seed))
}
//-------------------------------------
var _ crypto.PubKey = PubKey{}
// PubKeySize is the number of bytes in an Ed25519 signature.
const PubKeySize = 32
// PubKey implements crypto.PubKey for the Ed25519 signature scheme.
type PubKey [PubKeySize]byte
// PubKeyEd25519 implements crypto.PubKey for the Ed25519 signature scheme.
type PubKey []byte
// Address is the SHA256-20 of the raw pubkey bytes.
func (pubKey PubKey) Address() crypto.Address {
return crypto.Address(tmhash.SumTruncated(pubKey[:]))
if len(pubKey) != PubKeySize {
panic("pubkey is incorrect size")
}
return crypto.Address(tmhash.SumTruncated(pubKey))
}
// Bytes marshals the PubKey using amino encoding.
// Bytes returns the PubKey byte format.
func (pubKey PubKey) Bytes() []byte {
bz, err := cdc.MarshalBinaryBare(pubKey)
if err != nil {
panic(err)
}
return bz
return []byte(pubKey)
}
func (pubKey PubKey) VerifyBytes(msg []byte, sig []byte) bool {
@@ -153,11 +138,11 @@ func (pubKey PubKey) VerifyBytes(msg []byte, sig []byte) bool {
if len(sig) != SignatureSize {
return false
}
return ed25519.Verify(pubKey[:], msg, sig)
return ed25519.Verify(ed25519.PublicKey(pubKey), msg, sig)
}
func (pubKey PubKey) String() string {
return fmt.Sprintf("PubKey{%X}", pubKey[:])
return fmt.Sprintf("PubKeyEd25519{%X}", []byte(pubKey))
}
func (pubKey PubKey) Equals(other crypto.PubKey) bool {

View File

@@ -0,0 +1,18 @@
package ed25519
import (
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/crypto"
)
var cdc = amino.NewCodec()
func init() {
cdc.RegisterInterface((*crypto.PubKey)(nil), nil)
cdc.RegisterConcrete(PubKey{},
PubKeyAminoName, nil)
cdc.RegisterInterface((*crypto.PrivKey)(nil), nil)
cdc.RegisterConcrete(PrivKey{},
PrivKeyAminoName, nil)
}

View File

@@ -1,7 +1,6 @@
package cryptoamino
import (
"os"
"reflect"
"testing"
@@ -17,17 +16,20 @@ import (
"github.com/tendermint/tendermint/crypto/sr25519"
)
type byter interface {
Bytes() []byte
type AminoMarshal interface {
AminoMarshal() ([]byte, error)
AminoUnmarshal([]byte) error
}
func checkAminoBinary(t *testing.T, src, dst interface{}, size int) {
// Marshal to binary bytes.
bz, err := cdc.MarshalBinaryBare(src)
require.Nil(t, err, "%+v", err)
if byterSrc, ok := src.(byter); ok {
if byterSrc, ok := src.(AminoMarshal); ok {
// Make sure this is compatible with current (Bytes()) encoding.
assert.Equal(t, byterSrc.Bytes(), bz, "Amino binary vs Bytes() mismatch")
bza, err := byterSrc.AminoMarshal()
assert.NoError(t, err)
assert.Equal(t, bza, bz, "Amino binary vs Bytes() mismatch")
}
// Make sure we have the expected length.
assert.Equal(t, size, len(bz), "Amino binary size mismatch")
@@ -52,21 +54,6 @@ func checkAminoJSON(t *testing.T, src interface{}, dst interface{}, isNil bool)
require.Nil(t, err, "%+v", err)
}
// ExamplePrintRegisteredTypes refers to unknown identifier: PrintRegisteredTypes
//nolint:govet
func ExamplePrintRegisteredTypes() {
cdc.PrintTypes(os.Stdout)
// Output: | Type | Name | Prefix | Length | Notes |
//| ---- | ---- | ------ | ----- | ------ |
//| PubKey | tendermint/PubKeyEd25519 | 0x1624DE64 | 0x20 | |
//| PubKey | tendermint/PubKeySr25519 | 0x0DFB1005 | 0x20 | |
//| PubKey | tendermint/PubKeySecp256k1 | 0xEB5AE987 | 0x21 | |
//| PubKey | tendermint/PubKeyMultisigThreshold | 0x22C1F7E2 | variable | |
//| PrivKey | tendermint/PrivKeyEd25519 | 0xA3288910 | 0x40 | |
//| PrivKey | tendermint/PrivKeySr25519 | 0x2F82D78B | 0x20 | |
//| PrivKey | tendermint/PrivKeySecp256k1 | 0xE1B0F79B | 0x20 | |
}
func TestKeyEncodings(t *testing.T) {
cases := []struct {
privKey crypto.PrivKey

View File

@@ -16,7 +16,7 @@ func PubKeyToProto(k crypto.PubKey) (pc.PublicKey, error) {
case ed25519.PubKey:
kp = pc.PublicKey{
Sum: &pc.PublicKey_Ed25519{
Ed25519: k[:],
Ed25519: k,
},
}
default:
@@ -33,8 +33,8 @@ func PubKeyFromProto(k pc.PublicKey) (crypto.PubKey, error) {
return nil, fmt.Errorf("invalid size for PubKeyEd25519. Got %d, expected %d",
len(k.Ed25519), ed25519.PubKeySize)
}
var pk ed25519.PubKey
copy(pk[:], k.Ed25519)
pk := make(ed25519.PubKey, ed25519.PubKeySize)
copy(pk, k.Ed25519)
return pk, nil
default:
return nil, fmt.Errorf("fromproto: key type %v is not supported", k)
@@ -48,7 +48,7 @@ func PrivKeyToProto(k crypto.PrivKey) (pc.PrivateKey, error) {
case ed25519.PrivKey:
kp = pc.PrivateKey{
Sum: &pc.PrivateKey_Ed25519{
Ed25519: k[:],
Ed25519: k,
},
}
default:
@@ -66,8 +66,8 @@ func PrivKeyFromProto(k pc.PrivateKey) (crypto.PrivKey, error) {
return nil, fmt.Errorf("invalid size for PubKeyEd25519. Got %d, expected %d",
len(k.Ed25519), ed25519.PubKeySize)
}
var pk ed25519.PrivKey
copy(pk[:], k.Ed25519)
pk := make(ed25519.PrivKey, ed25519.PrivateKeySize)
copy(pk, k.Ed25519)
return pk, nil
default:
return nil, errors.New("fromproto: key type not supported")

View File

@@ -0,0 +1,23 @@
package secp256k1
import (
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/crypto"
)
const (
PrivKeyAminoName = "tendermint/PrivKeySecp256k1"
PubKeyAminoName = "tendermint/PubKeySecp256k1"
)
var cdc = amino.NewCodec()
func init() {
cdc.RegisterInterface((*crypto.PubKey)(nil), nil)
cdc.RegisterConcrete(PubKey{},
PubKeyAminoName, nil)
cdc.RegisterInterface((*crypto.PrivKey)(nil), nil)
cdc.RegisterConcrete(PrivKey{},
PrivKeyAminoName, nil)
}

View File

@@ -11,48 +11,26 @@ import (
secp256k1 "github.com/btcsuite/btcd/btcec"
"golang.org/x/crypto/ripemd160" // nolint: staticcheck // necessary for Bitcoin address format
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/crypto"
)
//-------------------------------------
const (
PrivKeyAminoName = "tendermint/PrivKeySecp256k1"
PubKeyAminoName = "tendermint/PubKeySecp256k1"
)
var cdc = amino.NewCodec()
func init() {
cdc.RegisterInterface((*crypto.PubKey)(nil), nil)
cdc.RegisterConcrete(PubKey{},
PubKeyAminoName, nil)
cdc.RegisterInterface((*crypto.PrivKey)(nil), nil)
cdc.RegisterConcrete(PrivKey{},
PrivKeyAminoName, nil)
}
//-------------------------------------
var _ crypto.PrivKey = PrivKey{}
const PrivKeySize = 32
// PrivKey implements PrivKey.
type PrivKey [32]byte
type PrivKey []byte
// Bytes marshalls the private key using amino encoding.
func (privKey PrivKey) Bytes() []byte {
return cdc.MustMarshalBinaryBare(privKey)
return []byte(privKey)
}
// PubKey performs the point-scalar multiplication from the privKey on the
// generator point to get the pubkey.
func (privKey PrivKey) PubKey() crypto.PubKey {
_, pubkeyObject := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:])
var pubkeyBytes PubKey
copy(pubkeyBytes[:], pubkeyObject.SerializeCompressed())
return pubkeyBytes
_, pubkeyObject := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey)
return PubKey(pubkeyObject.SerializeCompressed())
}
// Equals - you probably don't need to use this.
@@ -72,10 +50,10 @@ func GenPrivKey() PrivKey {
// genPrivKey generates a new secp256k1 private key using the provided reader.
func genPrivKey(rand io.Reader) PrivKey {
var privKeyBytes [32]byte
var privKeyBytes [PrivKeySize]byte
d := new(big.Int)
for {
privKeyBytes = [32]byte{}
privKeyBytes = [PrivKeySize]byte{}
_, err := io.ReadFull(rand, privKeyBytes[:])
if err != nil {
panic(err)
@@ -89,7 +67,7 @@ func genPrivKey(rand io.Reader) PrivKey {
}
}
return PrivKey(privKeyBytes)
return PrivKey(privKeyBytes[:])
}
var one = new(big.Int).SetInt64(1)
@@ -116,7 +94,7 @@ func GenPrivKeySecp256k1(secret []byte) PrivKey {
fe.Add(fe, one)
feB := fe.Bytes()
var privKey32 [32]byte
privKey32 := make([]byte, PrivKeySize)
// copy feB over to fixed 32 byte privKey32 and pad (if necessary)
copy(privKey32[32-len(feB):32], feB)
@@ -136,12 +114,16 @@ const PubKeySize = 33
// if the y-coordinate is the lexicographically largest of the two associated with
// the x-coordinate. Otherwise the first byte is a 0x03.
// This prefix is followed with the x-coordinate.
type PubKey [PubKeySize]byte
type PubKey []byte
// Address returns a Bitcoin style addresses: RIPEMD160(SHA256(pubkey))
func (pubKey PubKey) Address() crypto.Address {
if len(pubKey) != PubKeySize {
panic("length of pubkey is incorrect")
}
hasherSHA256 := sha256.New()
hasherSHA256.Write(pubKey[:]) // does not error
hasherSHA256.Write(pubKey) // does not error
sha := hasherSHA256.Sum(nil)
hasherRIPEMD160 := ripemd160.New()
@@ -149,17 +131,13 @@ func (pubKey PubKey) Address() crypto.Address {
return crypto.Address(hasherRIPEMD160.Sum(nil))
}
// Bytes returns the pubkey marshalled with amino encoding.
// Bytes returns the pubkey byte format.
func (pubKey PubKey) Bytes() []byte {
bz, err := cdc.MarshalBinaryBare(pubKey)
if err != nil {
panic(err)
}
return bz
return []byte(pubKey)
}
func (pubKey PubKey) String() string {
return fmt.Sprintf("PubKey{%X}", pubKey[:])
return fmt.Sprintf("PubKeySecp256k1{%X}", []byte(pubKey))
}
func (pubKey PubKey) Equals(other crypto.PubKey) bool {

View File

@@ -36,15 +36,13 @@ func TestPubKeySecp256k1Address(t *testing.T) {
addrBbz, _, _ := base58.CheckDecode(d.addr)
addrB := crypto.Address(addrBbz)
var priv secp256k1.PrivKey
copy(priv[:], privB)
var priv secp256k1.PrivKey = privB
pubKey := priv.PubKey()
pubT, _ := pubKey.(secp256k1.PubKey)
pub := pubT[:]
addr := pubKey.Address()
assert.Equal(t, pub, pubB, "Expected pub keys to match")
addr := pubKey.Address()
assert.Equal(t, pubT, secp256k1.PubKey(pubB), "Expected pub keys to match")
assert.Equal(t, addr, addrB, "Expected addresses to match")
}
}

View File

@@ -1,8 +1,7 @@
package sr25519
import (
amino "github.com/tendermint/go-amino"
"github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/crypto"
)

View File

@@ -13,17 +13,19 @@ import (
// PrivKeySize is the number of bytes in an Sr25519 private key.
const PrivKeySize = 32
// PrivKey implements crypto.PrivKey.
type PrivKey [PrivKeySize]byte
// PrivKeySr25519 implements crypto.PrivKey.
type PrivKey []byte
// Bytes marshals the privkey using amino encoding.
func (privKey PrivKey) Bytes() []byte {
return cdc.MustMarshalBinaryBare(privKey)
return []byte(privKey)
}
// Sign produces a signature on the provided message.
func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
miniSecretKey, err := schnorrkel.NewMiniSecretKeyFromRaw(privKey)
var p [PrivKeySize]byte
copy(p[:], privKey)
miniSecretKey, err := schnorrkel.NewMiniSecretKeyFromRaw(p)
if err != nil {
return []byte{}, err
}
@@ -42,7 +44,9 @@ func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
// PubKey gets the corresponding public key from the private key.
func (privKey PrivKey) PubKey() crypto.PubKey {
miniSecretKey, err := schnorrkel.NewMiniSecretKeyFromRaw(privKey)
var p [PrivKeySize]byte
copy(p[:], privKey)
miniSecretKey, err := schnorrkel.NewMiniSecretKeyFromRaw(p)
if err != nil {
panic(fmt.Sprintf("Invalid private key: %v", err))
}
@@ -52,8 +56,8 @@ func (privKey PrivKey) PubKey() crypto.PubKey {
if err != nil {
panic(fmt.Sprintf("Could not generate public key: %v", err))
}
return PubKey(pubkey.Encode())
key := pubkey.Encode()
return PubKey(key[:])
}
// Equals - you probably don't need to use this.
@@ -84,7 +88,8 @@ func genPrivKey(rand io.Reader) PrivKey {
copy(seed[:], out)
return schnorrkel.NewMiniSecretKey(seed).ExpandEd25519().Encode()
key := schnorrkel.NewMiniSecretKey(seed).ExpandEd25519().Encode()
return key[:]
}
// GenPrivKeyFromSecret hashes the secret with SHA2, and uses
@@ -96,5 +101,6 @@ func GenPrivKeyFromSecret(secret []byte) PrivKey {
var bz [PrivKeySize]byte
copy(bz[:], seed)
privKey, _ := schnorrkel.NewMiniSecretKeyFromRaw(bz)
return privKey.ExpandEd25519().Encode()
key := privKey.ExpandEd25519().Encode()
return key[:]
}

View File

@@ -15,8 +15,8 @@ var _ crypto.PubKey = PubKey{}
// PubKeySize is the number of bytes in an Sr25519 public key.
const PubKeySize = 32
// PubKey implements crypto.PubKey for the Sr25519 signature scheme.
type PubKey [PubKeySize]byte
// PubKeySr25519 implements crypto.PubKey for the Sr25519 signature scheme.
type PubKey []byte
// Address is the SHA256-20 of the raw pubkey bytes.
func (pubKey PubKey) Address() crypto.Address {
@@ -25,11 +25,7 @@ func (pubKey PubKey) Address() crypto.Address {
// Bytes marshals the PubKey using amino encoding.
func (pubKey PubKey) Bytes() []byte {
bz, err := cdc.MarshalBinaryBare(pubKey)
if err != nil {
panic(err)
}
return bz
return []byte(pubKey)
}
func (pubKey PubKey) VerifyBytes(msg []byte, sig []byte) bool {
@@ -41,7 +37,9 @@ func (pubKey PubKey) VerifyBytes(msg []byte, sig []byte) bool {
copy(sig64[:], sig)
publicKey := &(schnorrkel.PublicKey{})
err := publicKey.Decode(pubKey)
var p [PubKeySize]byte
copy(p[:], pubKey)
err := publicKey.Decode(p)
if err != nil {
return false
}
@@ -58,7 +56,7 @@ func (pubKey PubKey) VerifyBytes(msg []byte, sig []byte) bool {
}
func (pubKey PubKey) String() string {
return fmt.Sprintf("PubKey{%X}", pubKey[:])
return fmt.Sprintf("PubKeySr25519{%X}", []byte(pubKey))
}
// Equals - checks that two public keys are the same time