crypto: Remove interface from crypto.Signature

Signatures are now []byte, which saves on the number of bytes after
amino encoding

(squash this) address Ismail's comment
This commit is contained in:
ValarDragon
2018-08-01 17:02:05 -07:00
committed by Ethan Buchman
parent d6a666b445
commit f903947ff3
21 changed files with 69 additions and 182 deletions

View File

@ -24,9 +24,7 @@ crypto `.Bytes()` uses Amino:binary encoding, but Amino:JSON is also supported.
Example Amino:JSON encodings:
ed25519.PrivKeyEd25519 - {"type":"954568A3288910","value":"EVkqJO/jIXp3rkASXfh9YnyToYXRXhBr6g9cQVxPFnQBP/5povV4HTjvsy530kybxKHwEi85iU8YL0qQhSYVoQ=="}
crypto.SignatureEd25519 - {"type":"6BF5903DA1DB28","value":"77sQNZOrf7ltExpf7AV1WaYPCHbyRLgjBsoWVzcduuLk+jIGmYk+s5R6Emm29p12HeiNAuhUJgdFGmwkpeGJCA=="}
ed25519.PubKeyEd25519 - {"type":"AC26791624DE60","value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE="}
crypto.PrivKeySecp256k1 - {"type":"019E82E1B0F798","value":"zx4Pnh67N+g2V+5vZbQzEyRerX9c4ccNZOVzM9RvJ0Y="}
crypto.SignatureSecp256k1 - {"type":"6D1EA416E1FEE8","value":"MEUCIQCIg5TqS1l7I+MKTrSPIuUN2+4m5tA29dcauqn3NhEJ2wIgICaZ+lgRc5aOTVahU/XoLopXKn8BZcl0bnuYWLvohR8="}
crypto.PubKeySecp256k1 - {"type":"F8CCEAEB5AE980","value":"A8lPKJXcNl5VHt1FK8a244K9EJuS4WX1hFBnwisi0IJx"}
```

View File

@ -6,7 +6,7 @@ import (
type PrivKey interface {
Bytes() []byte
Sign(msg []byte) (Signature, error)
Sign(msg []byte) ([]byte, error)
PubKey() PubKey
Equals(PrivKey) bool
}
@ -19,16 +19,10 @@ type Address = cmn.HexBytes
type PubKey interface {
Address() Address
Bytes() []byte
VerifyBytes(msg []byte, sig Signature) bool
VerifyBytes(msg []byte, sig []byte) bool
Equals(PubKey) bool
}
type Signature interface {
Bytes() []byte
IsZero() bool
Equals(Signature) bool
}
type Symmetric interface {
Keygen() []byte
Encrypt(plaintext []byte, secret []byte) (ciphertext []byte)

View File

@ -11,7 +11,6 @@ import (
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/tmhash"
cmn "github.com/tendermint/tendermint/libs/common"
)
//-------------------------------------
@ -19,9 +18,11 @@ import (
var _ crypto.PrivKey = PrivKeyEd25519{}
const (
Ed25519PrivKeyAminoRoute = "tendermint/PrivKeyEd25519"
Ed25519PubKeyAminoRoute = "tendermint/PubKeyEd25519"
Ed25519SignatureAminoRoute = "tendermint/SignatureEd25519"
Ed25519PrivKeyAminoRoute = "tendermint/PrivKeyEd25519"
Ed25519PubKeyAminoRoute = "tendermint/PubKeyEd25519"
// Size of an Edwards25519 signature. Namely the size of a compressed
// Edwards25519 point, and a field element. Both of which are 32 bytes.
SignatureEd25519Size = 64
)
var cdc = amino.NewCodec()
@ -34,10 +35,6 @@ func init() {
cdc.RegisterInterface((*crypto.PrivKey)(nil), nil)
cdc.RegisterConcrete(PrivKeyEd25519{},
Ed25519PrivKeyAminoRoute, nil)
cdc.RegisterInterface((*crypto.Signature)(nil), nil)
cdc.RegisterConcrete(SignatureEd25519{},
Ed25519SignatureAminoRoute, nil)
}
// PrivKeyEd25519 implements crypto.PrivKey.
@ -49,10 +46,10 @@ func (privKey PrivKeyEd25519) Bytes() []byte {
}
// Sign produces a signature on the provided message.
func (privKey PrivKeyEd25519) Sign(msg []byte) (crypto.Signature, error) {
func (privKey PrivKeyEd25519) Sign(msg []byte) ([]byte, error) {
privKeyBytes := [64]byte(privKey)
signatureBytes := ed25519.Sign(&privKeyBytes, msg)
return SignatureEd25519(*signatureBytes), nil
return signatureBytes[:], nil
}
// PubKey gets the corresponding public key from the private key.
@ -159,15 +156,15 @@ func (pubKey PubKeyEd25519) Bytes() []byte {
return bz
}
func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ crypto.Signature) bool {
func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ []byte) bool {
// make sure we use the same algorithm to sign
sig, ok := sig_.(SignatureEd25519)
if !ok {
if len(sig_) != SignatureEd25519Size {
return false
}
sig := new([SignatureEd25519Size]byte)
copy(sig[:], sig_)
pubKeyBytes := [PubKeyEd25519Size]byte(pubKey)
sigBytes := [SignatureEd25519Size]byte(sig)
return ed25519.Verify(&pubKeyBytes, msg, &sigBytes)
return ed25519.Verify(&pubKeyBytes, msg, sig)
}
// ToCurve25519 takes a public key and returns its representation on
@ -197,40 +194,3 @@ func (pubKey PubKeyEd25519) Equals(other crypto.PubKey) bool {
return false
}
}
//-------------------------------------
var _ crypto.Signature = SignatureEd25519{}
// Size of an Edwards25519 signature. Namely the size of a compressed
// Edwards25519 point, and a field element. Both of which are 32 bytes.
const SignatureEd25519Size = 64
// SignatureEd25519 implements crypto.Signature
type SignatureEd25519 [SignatureEd25519Size]byte
func (sig SignatureEd25519) Bytes() []byte {
bz, err := cdc.MarshalBinaryBare(sig)
if err != nil {
panic(err)
}
return bz
}
func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 }
func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", cmn.Fingerprint(sig[:])) }
func (sig SignatureEd25519) Equals(other crypto.Signature) bool {
if otherEd, ok := other.(SignatureEd25519); ok {
return subtle.ConstantTimeCompare(sig[:], otherEd[:]) == 1
} else {
return false
}
}
func SignatureEd25519FromBytes(data []byte) crypto.Signature {
var sig SignatureEd25519
copy(sig[:], data)
return sig
}

View File

@ -23,9 +23,7 @@ func TestSignAndValidateEd25519(t *testing.T) {
// Mutate the signature, just one bit.
// TODO: Replace this with a much better fuzzer, tendermint/ed25519/issues/10
sigEd := sig.(ed25519.SignatureEd25519)
sigEd[7] ^= byte(0x01)
sig = sigEd
sig[7] ^= byte(0x01)
assert.False(t, pubKey.VerifyBytes(msg, sig))
}

View File

@ -33,12 +33,6 @@ func RegisterAmino(cdc *amino.Codec) {
"tendermint/PrivKeyEd25519", nil)
cdc.RegisterConcrete(secp256k1.PrivKeySecp256k1{},
"tendermint/PrivKeySecp256k1", nil)
cdc.RegisterInterface((*crypto.Signature)(nil), nil)
cdc.RegisterConcrete(ed25519.SignatureEd25519{},
"tendermint/SignatureEd25519", nil)
cdc.RegisterConcrete(secp256k1.SignatureSecp256k1{},
"tendermint/SignatureSecp256k1", nil)
}
func PrivKeyFromBytes(privKeyBytes []byte) (privKey crypto.PrivKey, err error) {
@ -50,8 +44,3 @@ func PubKeyFromBytes(pubKeyBytes []byte) (pubKey crypto.PubKey, err error) {
err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey)
return
}
func SignatureFromBytes(pubKeyBytes []byte) (pubKey crypto.Signature, err error) {
err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey)
return
}

View File

@ -15,12 +15,14 @@ type byter interface {
Bytes() []byte
}
func checkAminoBinary(t *testing.T, src byter, dst interface{}, size int) {
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)
// Make sure this is compatible with current (Bytes()) encoding.
assert.Equal(t, src.Bytes(), bz, "Amino binary vs Bytes() mismatch")
if byterSrc, ok := src.(byter); ok {
// Make sure this is compatible with current (Bytes()) encoding.
assert.Equal(t, byterSrc.Bytes(), bz, "Amino binary vs Bytes() mismatch")
}
// Make sure we have the expected length.
if size != -1 {
assert.Equal(t, size, len(bz), "Amino binary size mismatch")
@ -53,8 +55,6 @@ func ExamplePrintRegisteredTypes() {
//| PubKeySecp256k1 | tendermint/PubKeySecp256k1 | 0xEB5AE987 | 0x21 | |
//| PrivKeyEd25519 | tendermint/PrivKeyEd25519 | 0xA3288910 | 0x40 | |
//| PrivKeySecp256k1 | tendermint/PrivKeySecp256k1 | 0xE1B0F79B | 0x20 | |
//| SignatureEd25519 | tendermint/SignatureEd25519 | 0x2031EA53 | 0x40 | |
//| SignatureSecp256k1 | tendermint/SignatureSecp256k1 | 0x7FC4A495 | variable | |
}
func TestKeyEncodings(t *testing.T) {
@ -84,13 +84,11 @@ func TestKeyEncodings(t *testing.T) {
assert.EqualValues(t, tc.privKey, priv3, "tc #%d", tcIndex)
// Check (de/en)codings of Signatures.
var sig1, sig2, sig3 crypto.Signature
var sig1, sig2 []byte
sig1, err := tc.privKey.Sign([]byte("something"))
assert.NoError(t, err, "tc #%d", tcIndex)
checkAminoBinary(t, sig1, &sig2, -1) // Signature size changes for Secp anyways.
assert.EqualValues(t, sig1, sig2, "tc #%d", tcIndex)
checkAminoJSON(t, sig1, &sig3, false) // TODO also check Prefix bytes.
assert.EqualValues(t, sig1, sig3, "tc #%d", tcIndex)
// Check (de/en)codings of PubKeys.
pubKey := tc.privKey.PubKey()
@ -105,7 +103,7 @@ func TestKeyEncodings(t *testing.T) {
func TestNilEncodings(t *testing.T) {
// Check nil Signature.
var a, b crypto.Signature
var a, b []byte
checkAminoJSON(t, &a, &b, true)
assert.EqualValues(t, a, b)

View File

@ -10,15 +10,13 @@ import (
secp256k1 "github.com/btcsuite/btcd/btcec"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/libs/common"
"golang.org/x/crypto/ripemd160"
)
//-------------------------------------
const (
Secp256k1PrivKeyAminoRoute = "tendermint/PrivKeySecp256k1"
Secp256k1PubKeyAminoRoute = "tendermint/PubKeySecp256k1"
Secp256k1SignatureAminoRoute = "tendermint/SignatureSecp256k1"
Secp256k1PrivKeyAminoRoute = "tendermint/PrivKeySecp256k1"
Secp256k1PubKeyAminoRoute = "tendermint/PubKeySecp256k1"
)
var cdc = amino.NewCodec()
@ -31,10 +29,6 @@ func init() {
cdc.RegisterInterface((*crypto.PrivKey)(nil), nil)
cdc.RegisterConcrete(PrivKeySecp256k1{},
Secp256k1PrivKeyAminoRoute, nil)
cdc.RegisterInterface((*crypto.Signature)(nil), nil)
cdc.RegisterConcrete(SignatureSecp256k1{},
Secp256k1SignatureAminoRoute, nil)
}
//-------------------------------------
@ -50,13 +44,13 @@ func (privKey PrivKeySecp256k1) Bytes() []byte {
}
// Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg.
func (privKey PrivKeySecp256k1) Sign(msg []byte) (crypto.Signature, error) {
func (privKey PrivKeySecp256k1) Sign(msg []byte) ([]byte, error) {
priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:])
sig, err := priv.Sign(crypto.Sha256(msg))
if err != nil {
return nil, err
}
return SignatureSecp256k1(sig.Serialize()), nil
return sig.Serialize(), nil
}
// PubKey performs the point-scalar multiplication from the privKey on the
@ -142,13 +136,7 @@ func (pubKey PubKeySecp256k1) Bytes() []byte {
return bz
}
func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, interfaceSig crypto.Signature) bool {
// and assert same algorithm to sign and verify
sig, ok := interfaceSig.(SignatureSecp256k1)
if !ok {
return false
}
func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig []byte) bool {
pub, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256())
if err != nil {
return false
@ -170,38 +158,3 @@ func (pubKey PubKeySecp256k1) Equals(other crypto.PubKey) bool {
}
return false
}
//-------------------------------------
var _ crypto.Signature = SignatureSecp256k1{}
// SignatureSecp256k1 implements crypto.Signature
type SignatureSecp256k1 []byte
func (sig SignatureSecp256k1) Bytes() []byte {
bz, err := cdc.MarshalBinaryBare(sig)
if err != nil {
panic(err)
}
return bz
}
func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 }
func (sig SignatureSecp256k1) String() string {
return fmt.Sprintf("/%X.../", common.Fingerprint(sig[:]))
}
func (sig SignatureSecp256k1) Equals(other crypto.Signature) bool {
if otherSecp, ok := other.(SignatureSecp256k1); ok {
return subtle.ConstantTimeCompare(sig[:], otherSecp[:]) == 1
} else {
return false
}
}
func SignatureSecp256k1FromBytes(data []byte) crypto.Signature {
sig := make(SignatureSecp256k1, len(data))
copy(sig[:], data)
return sig
}

View File

@ -59,9 +59,7 @@ func TestSignAndValidateSecp256k1(t *testing.T) {
assert.True(t, pubKey.VerifyBytes(msg, sig))
// Mutate the signature, just one bit.
sigEd := sig.(secp256k1.SignatureSecp256k1)
sigEd[3] ^= byte(0x01)
sig = sigEd
sig[3] ^= byte(0x01)
assert.False(t, pubKey.VerifyBytes(msg, sig))
}