From d157095e31ab08b94fc3b7bfbf5806719f96e572 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 13 Jul 2018 17:56:13 +0200 Subject: [PATCH 1/4] feat: refactor key interface This now allows full access to the raw bytes of all keys and unifies pb marshals cc @stebalien --- ed25519.go | 33 ++++++++++++++++++++------------- key.go | 35 ++++++++++++++++++++++++----------- key_test.go | 11 ++++++++++- rsa.go | 32 +++++++++++++++++--------------- secp256k1.go | 33 ++++++++++++++++++++------------- 5 files changed, 91 insertions(+), 53 deletions(-) diff --git a/ed25519.go b/ed25519.go index 385e0b9..298b90f 100644 --- a/ed25519.go +++ b/ed25519.go @@ -7,7 +7,6 @@ import ( "github.com/agl/ed25519" extra "github.com/agl/ed25519/extra25519" - proto "github.com/gogo/protobuf/proto" pb "github.com/libp2p/go-libp2p-crypto/pb" ) @@ -36,16 +35,20 @@ func GenerateEd25519Key(src io.Reader) (PrivKey, PubKey, error) { nil } -func (k *Ed25519PrivateKey) Bytes() ([]byte, error) { - pbmes := new(pb.PrivateKey) - typ := pb.KeyType_Ed25519 - pbmes.Type = &typ +func (sk *Ed25519PrivateKey) Type() pb.KeyType { + return pb.KeyType_Ed25519 +} + +func (sk *Ed25519PrivateKey) Bytes() ([]byte, error) { + return MarshalPrivateKey(sk) +} +func (k *Ed25519PrivateKey) Raw() ([]byte, error) { buf := make([]byte, 96) copy(buf, k.sk[:]) copy(buf[64:], k.pk[:]) - pbmes.Data = buf - return proto.Marshal(pbmes) + + return buf, nil } func (k *Ed25519PrivateKey) Equals(o Key) bool { @@ -72,12 +75,16 @@ func (k *Ed25519PrivateKey) ToCurve25519() *[32]byte { return &sk } -func (k *Ed25519PublicKey) Bytes() ([]byte, error) { - pbmes := new(pb.PublicKey) - typ := pb.KeyType_Ed25519 - pbmes.Type = &typ - pbmes.Data = (*k.k)[:] - return proto.Marshal(pbmes) +func (sk *Ed25519PublicKey) Type() pb.KeyType { + return pb.KeyType_Ed25519 +} + +func (sk *Ed25519PublicKey) Bytes() ([]byte, error) { + return MarshalPublicKey(sk) +} + +func (k *Ed25519PublicKey) Raw() ([]byte, error) { + return (*k.k)[:], nil } func (k *Ed25519PublicKey) Equals(o Key) bool { diff --git a/key.go b/key.go index 1a9d0ec..5a7443f 100644 --- a/key.go +++ b/key.go @@ -59,10 +59,17 @@ var PrivKeyUnmarshallers = map[pb.KeyType]PrivKeyUnmarshaller{ // Key represents a crypto key that can be compared to another key type Key interface { // Bytes returns a serialized, storeable representation of this key + // DEPRECATED in favor of Marshal / Unmarshal Bytes() ([]byte, error) // Equals checks whether two PubKeys are the same Equals(Key) bool + + // Raw returns the raw bytes of the key. + Raw() ([]byte, error) + + // Type returns the protobof key type. + Type() pb.KeyType } // PrivKey represents a private key that can be used to generate a public key, @@ -261,7 +268,15 @@ func UnmarshalPublicKey(data []byte) (PubKey, error) { // MarshalPublicKey converts a public key object into a protobuf serialized // public key func MarshalPublicKey(k PubKey) ([]byte, error) { - return k.Bytes() + pbmes := new(pb.PublicKey) + pbmes.Type = k.Type().Enum() + data, err := k.Raw() + if err != nil { + return nil, err + } + pbmes.Data = data + + return proto.Marshal(pbmes) } // UnmarshalPrivateKey converts a protobuf serialized private key into its @@ -283,17 +298,15 @@ func UnmarshalPrivateKey(data []byte) (PrivKey, error) { // MarshalPrivateKey converts a key object into its protobuf serialized form. func MarshalPrivateKey(k PrivKey) ([]byte, error) { - - switch k.(type) { - case *Ed25519PrivateKey: - return k.Bytes() - case *RsaPrivateKey: - return k.Bytes() - case *Secp256k1PrivateKey: - return k.Bytes() - default: - return nil, ErrBadKeyType + pbmes := new(pb.PrivateKey) + pbmes.Type = k.Type().Enum() + data, err := k.Raw() + if err != nil { + return nil, err } + + pbmes.Data = data + return proto.Marshal(pbmes) } // ConfigDecodeKey decodes from b64 (for config file), and unmarshals. diff --git a/key_test.go b/key_test.go index aa8b9c1..d8dbf22 100644 --- a/key_test.go +++ b/key_test.go @@ -3,7 +3,8 @@ package crypto_test import ( . "github.com/libp2p/go-libp2p-crypto" tu "github.com/libp2p/go-libp2p-crypto/test" - + pb "github.com/libp2p/go-libp2p-crypto/pb" + "bytes" "crypto/rand" "testing" @@ -131,6 +132,14 @@ func (pk testkey) Bytes() ([]byte, error) { return pk, nil } +func (pk testkey) Type() pb.KeyType { + return pb.KeyType_RSA +} + +func (pk testkey) Raw() ([]byte, error) { + return pk, nil +} + func (pk testkey) Equals(k Key) bool { return KeyEqual(pk, k) } diff --git a/rsa.go b/rsa.go index f3c2acd..8a9e58a 100644 --- a/rsa.go +++ b/rsa.go @@ -9,7 +9,6 @@ import ( pb "github.com/libp2p/go-libp2p-crypto/pb" - proto "github.com/gogo/protobuf/proto" sha256 "github.com/minio/sha256-simd" ) @@ -31,17 +30,16 @@ func (pk *RsaPublicKey) Verify(data, sig []byte) (bool, error) { return true, nil } +func (pk *RsaPublicKey) Type() pb.KeyType { + return pb.KeyType_RSA +} + func (pk *RsaPublicKey) Bytes() ([]byte, error) { - b, err := x509.MarshalPKIXPublicKey(pk.k) - if err != nil { - return nil, err - } + return MarshalPublicKey(pk) +} - pbmes := new(pb.PublicKey) - typ := pb.KeyType_RSA - pbmes.Type = &typ - pbmes.Data = b - return proto.Marshal(pbmes) +func (pk *RsaPublicKey) Raw() ([]byte, error) { + return x509.MarshalPKIXPublicKey(pk.k) } func (pk *RsaPublicKey) Encrypt(b []byte) ([]byte, error) { @@ -69,13 +67,17 @@ func (sk *RsaPrivateKey) Decrypt(b []byte) ([]byte, error) { return rsa.DecryptPKCS1v15(rand.Reader, sk.sk, b) } +func (sk *RsaPrivateKey) Type() pb.KeyType { + return pb.KeyType_RSA +} + func (sk *RsaPrivateKey) Bytes() ([]byte, error) { + return MarshalPrivateKey(sk) +} + +func (sk *RsaPrivateKey) Raw() ([]byte, error) { b := x509.MarshalPKCS1PrivateKey(sk.sk) - pbmes := new(pb.PrivateKey) - typ := pb.KeyType_RSA - pbmes.Type = &typ - pbmes.Data = b - return proto.Marshal(pbmes) + return b, nil } // Equals checks whether this key is equal to another diff --git a/secp256k1.go b/secp256k1.go index 3ed37f1..0b7fa30 100644 --- a/secp256k1.go +++ b/secp256k1.go @@ -5,7 +5,6 @@ import ( "io" btcec "github.com/btcsuite/btcd/btcec" - proto "github.com/gogo/protobuf/proto" pb "github.com/libp2p/go-libp2p-crypto/pb" sha256 "github.com/minio/sha256-simd" ) @@ -41,12 +40,16 @@ func UnmarshalSecp256k1PublicKey(data []byte) (PubKey, error) { return (*Secp256k1PublicKey)(k), nil } -func (k *Secp256k1PrivateKey) Bytes() ([]byte, error) { - pbmes := new(pb.PrivateKey) - typ := pb.KeyType_Secp256k1 - pbmes.Type = &typ - pbmes.Data = (*btcec.PrivateKey)(k).Serialize() - return proto.Marshal(pbmes) +func (sk *Secp256k1PrivateKey) Type() pb.KeyType { + return pb.KeyType_Secp256k1 +} + +func (sk *Secp256k1PrivateKey) Bytes() ([]byte, error) { + return MarshalPrivateKey(sk) +} + +func (k *Secp256k1PrivateKey) Raw() ([]byte, error) { + return (*btcec.PrivateKey)(k).Serialize(), nil } func (k *Secp256k1PrivateKey) Equals(o Key) bool { @@ -72,12 +75,16 @@ func (k *Secp256k1PrivateKey) GetPublic() PubKey { return (*Secp256k1PublicKey)((*btcec.PrivateKey)(k).PubKey()) } -func (k *Secp256k1PublicKey) Bytes() ([]byte, error) { - pbmes := new(pb.PublicKey) - typ := pb.KeyType_Secp256k1 - pbmes.Type = &typ - pbmes.Data = (*btcec.PublicKey)(k).SerializeCompressed() - return proto.Marshal(pbmes) +func (sk *Secp256k1PublicKey) Type() pb.KeyType { + return pb.KeyType_Secp256k1 +} + +func (sk *Secp256k1PublicKey) Bytes() ([]byte, error) { + return MarshalPublicKey(sk) +} + +func (k *Secp256k1PublicKey) Raw() ([]byte, error) { + return (*btcec.PublicKey)(k).SerializeCompressed(), nil } func (k *Secp256k1PublicKey) Equals(o Key) bool { From 6e1141a8ae3b7d0d26eef81b807a7a26ad2628ac Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 24 Jul 2018 21:37:49 -0700 Subject: [PATCH 2/4] be consistent with receivers --- ed25519.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ed25519.go b/ed25519.go index 298b90f..45c0f86 100644 --- a/ed25519.go +++ b/ed25519.go @@ -35,12 +35,12 @@ func GenerateEd25519Key(src io.Reader) (PrivKey, PubKey, error) { nil } -func (sk *Ed25519PrivateKey) Type() pb.KeyType { +func (k *Ed25519PrivateKey) Type() pb.KeyType { return pb.KeyType_Ed25519 } -func (sk *Ed25519PrivateKey) Bytes() ([]byte, error) { - return MarshalPrivateKey(sk) +func (k *Ed25519PrivateKey) Bytes() ([]byte, error) { + return MarshalPrivateKey(k) } func (k *Ed25519PrivateKey) Raw() ([]byte, error) { @@ -75,12 +75,12 @@ func (k *Ed25519PrivateKey) ToCurve25519() *[32]byte { return &sk } -func (sk *Ed25519PublicKey) Type() pb.KeyType { +func (k *Ed25519PublicKey) Type() pb.KeyType { return pb.KeyType_Ed25519 } -func (sk *Ed25519PublicKey) Bytes() ([]byte, error) { - return MarshalPublicKey(sk) +func (k *Ed25519PublicKey) Bytes() ([]byte, error) { + return MarshalPublicKey(k) } func (k *Ed25519PublicKey) Raw() ([]byte, error) { From c45d7ec5fb0713e02a39033ab3f39d4a0c67453b Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 24 Jul 2018 21:39:35 -0700 Subject: [PATCH 3/4] add more documentation to the `Raw()` method --- key.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/key.go b/key.go index 5a7443f..7c483a8 100644 --- a/key.go +++ b/key.go @@ -65,7 +65,10 @@ type Key interface { // Equals checks whether two PubKeys are the same Equals(Key) bool - // Raw returns the raw bytes of the key. + // Raw returns the raw bytes of the key (not wrapped in the + // libp2p-crypto protobuf). + // + // This function is the inverse of {Priv,Pub}KeyUnmarshaler. Raw() ([]byte, error) // Type returns the protobof key type. @@ -275,7 +278,7 @@ func MarshalPublicKey(k PubKey) ([]byte, error) { return nil, err } pbmes.Data = data - + return proto.Marshal(pbmes) } @@ -304,7 +307,7 @@ func MarshalPrivateKey(k PrivKey) ([]byte, error) { if err != nil { return nil, err } - + pbmes.Data = data return proto.Marshal(pbmes) } From dda9e4b00bf4acc14a453188ca4852639d37596a Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 24 Jul 2018 21:39:46 -0700 Subject: [PATCH 4/4] go fmt --- key_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/key_test.go b/key_test.go index d8dbf22..cde8ab2 100644 --- a/key_test.go +++ b/key_test.go @@ -2,9 +2,9 @@ package crypto_test import ( . "github.com/libp2p/go-libp2p-crypto" - tu "github.com/libp2p/go-libp2p-crypto/test" pb "github.com/libp2p/go-libp2p-crypto/pb" - + tu "github.com/libp2p/go-libp2p-crypto/test" + "bytes" "crypto/rand" "testing"