From 628240fb522c70c34f17734b69ae03a0a2374d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 16 Jan 2020 01:29:26 +0000 Subject: [PATCH] Introduce routability and protocol events; cache unmarshalled RSA keys (#105) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * event: Add autonat events (#25) * add events for identify (#26) * implement caching for rsaKey.Bytes() * store marshalled protobuf in cache for RsaPublicKey.Bytes() * fix(crypto): fix build when openssl is enabled * add godocs to routability events. Co-authored-by: Ɓukasz Magiera Co-authored-by: Whyrusleeping Co-authored-by: Adin Schmahmann Co-authored-by: Steven Allen --- core/crypto/key.go | 14 +++++++++++++- core/crypto/key_not_openssl.go | 2 +- core/crypto/key_openssl.go | 2 +- core/crypto/openssl_common.go | 17 ++++++++++++++--- core/crypto/rsa_go.go | 19 +++++++++++++++---- core/crypto/rsa_openssl.go | 4 ++-- core/event/identify.go | 17 +++++++++++++++++ core/event/routability.go | 21 +++++++++++++++++++++ 8 files changed, 84 insertions(+), 12 deletions(-) create mode 100644 core/event/identify.go create mode 100644 core/event/routability.go diff --git a/core/crypto/key.go b/core/crypto/key.go index 3a5263665b..090338810f 100644 --- a/core/crypto/key.go +++ b/core/crypto/key.go @@ -294,7 +294,19 @@ func PublicKeyFromProto(pmes *pb.PublicKey) (PubKey, error) { return nil, ErrBadKeyType } - return um(pmes.GetData()) + data := pmes.GetData() + + pk, err := um(data) + if err != nil { + return nil, err + } + + switch tpk := pk.(type) { + case *RsaPublicKey: + tpk.cached, _ = pmes.Marshal() + } + + return pk, nil } // MarshalPublicKey converts a public key object into a protobuf serialized diff --git a/core/crypto/key_not_openssl.go b/core/crypto/key_not_openssl.go index 6b5b6fc2ce..fb1e36adf3 100644 --- a/core/crypto/key_not_openssl.go +++ b/core/crypto/key_not_openssl.go @@ -19,7 +19,7 @@ func KeyPairFromStdKey(priv crypto.PrivateKey) (PrivKey, PubKey, error) { switch p := priv.(type) { case *rsa.PrivateKey: - return &RsaPrivateKey{*p}, &RsaPublicKey{p.PublicKey}, nil + return &RsaPrivateKey{*p}, &RsaPublicKey{k: p.PublicKey}, nil case *ecdsa.PrivateKey: return &ECDSAPrivateKey{p}, &ECDSAPublicKey{&p.PublicKey}, nil diff --git a/core/crypto/key_openssl.go b/core/crypto/key_openssl.go index b948f3d081..5b1e3607ab 100644 --- a/core/crypto/key_openssl.go +++ b/core/crypto/key_openssl.go @@ -26,7 +26,7 @@ func KeyPairFromStdKey(priv crypto.PrivateKey) (PrivKey, PubKey, error) { return nil, nil, err } - return &opensslPrivateKey{pk}, &opensslPublicKey{pk}, nil + return &opensslPrivateKey{pk}, &opensslPublicKey{key: pk}, nil case *ecdsa.PrivateKey: return &ECDSAPrivateKey{p}, &ECDSAPublicKey{&p.PublicKey}, nil diff --git a/core/crypto/openssl_common.go b/core/crypto/openssl_common.go index 2466521c7a..88807cafd7 100644 --- a/core/crypto/openssl_common.go +++ b/core/crypto/openssl_common.go @@ -3,6 +3,8 @@ package crypto import ( + "sync" + pb "github.com/libp2p/go-libp2p-core/crypto/pb" openssl "github.com/libp2p/go-openssl" @@ -13,6 +15,9 @@ import ( type opensslPublicKey struct { key openssl.PublicKey + + cacheLk sync.Mutex + cached []byte } type opensslPrivateKey struct { @@ -32,7 +37,7 @@ func unmarshalOpensslPublicKey(b []byte) (opensslPublicKey, error) { if err != nil { return opensslPublicKey{}, err } - return opensslPublicKey{sk}, nil + return opensslPublicKey{key: sk, cached: b}, nil } // Verify compares a signature against input data @@ -52,7 +57,13 @@ func (pk *opensslPublicKey) Type() pb.KeyType { // Bytes returns protobuf bytes of a public key func (pk *opensslPublicKey) Bytes() ([]byte, error) { - return MarshalPublicKey(pk) + pk.cacheLk.Lock() + var err error + if pk.cached == nil { + pk.cached, err = MarshalPublicKey(pk) + } + pk.cacheLk.Unlock() + return pk.cached, err } func (pk *opensslPublicKey) Raw() ([]byte, error) { @@ -76,7 +87,7 @@ func (sk *opensslPrivateKey) Sign(message []byte) ([]byte, error) { // GetPublic returns a public key func (sk *opensslPrivateKey) GetPublic() PubKey { - return &opensslPublicKey{sk.key} + return &opensslPublicKey{key: sk.key} } func (sk *opensslPrivateKey) Type() pb.KeyType { diff --git a/core/crypto/rsa_go.go b/core/crypto/rsa_go.go index d774991941..f28a327b83 100644 --- a/core/crypto/rsa_go.go +++ b/core/crypto/rsa_go.go @@ -9,6 +9,7 @@ import ( "crypto/x509" "errors" "io" + "sync" pb "github.com/libp2p/go-libp2p-core/crypto/pb" @@ -23,6 +24,9 @@ type RsaPrivateKey struct { // RsaPublicKey is an rsa public key type RsaPublicKey struct { k rsa.PublicKey + + cacheLk sync.Mutex + cached []byte } // GenerateRSAKeyPair generates a new rsa private and public key @@ -35,7 +39,7 @@ func GenerateRSAKeyPair(bits int, src io.Reader) (PrivKey, PubKey, error) { return nil, nil, err } pk := priv.PublicKey - return &RsaPrivateKey{sk: *priv}, &RsaPublicKey{pk}, nil + return &RsaPrivateKey{sk: *priv}, &RsaPublicKey{k: pk}, nil } // Verify compares a signature against input data @@ -54,7 +58,13 @@ func (pk *RsaPublicKey) Type() pb.KeyType { // Bytes returns protobuf bytes of a public key func (pk *RsaPublicKey) Bytes() ([]byte, error) { - return MarshalPublicKey(pk) + pk.cacheLk.Lock() + var err error + if pk.cached == nil { + pk.cached, err = MarshalPublicKey(pk) + } + pk.cacheLk.Unlock() + return pk.cached, err } func (pk *RsaPublicKey) Raw() ([]byte, error) { @@ -80,7 +90,7 @@ func (sk *RsaPrivateKey) Sign(message []byte) ([]byte, error) { // GetPublic returns a public key func (sk *RsaPrivateKey) GetPublic() PubKey { - return &RsaPublicKey{sk.sk.PublicKey} + return &RsaPublicKey{k: sk.sk.PublicKey} } func (sk *RsaPrivateKey) Type() pb.KeyType { @@ -137,5 +147,6 @@ func UnmarshalRsaPublicKey(b []byte) (PubKey, error) { if pk.N.BitLen() < MinRsaKeyBits { return nil, ErrRsaKeyTooSmall } - return &RsaPublicKey{*pk}, nil + + return &RsaPublicKey{k: *pk}, nil } diff --git a/core/crypto/rsa_openssl.go b/core/crypto/rsa_openssl.go index 9b7a342345..8e7fb74315 100644 --- a/core/crypto/rsa_openssl.go +++ b/core/crypto/rsa_openssl.go @@ -29,12 +29,12 @@ func GenerateRSAKeyPair(bits int, _ io.Reader) (PrivKey, PubKey, error) { if err != nil { return nil, nil, err } - return &RsaPrivateKey{opensslPrivateKey{key}}, &RsaPublicKey{opensslPublicKey{key}}, nil + return &RsaPrivateKey{opensslPrivateKey{key}}, &RsaPublicKey{opensslPublicKey{key: key}}, nil } // GetPublic returns a public key func (sk *RsaPrivateKey) GetPublic() PubKey { - return &RsaPublicKey{opensslPublicKey{sk.opensslPrivateKey.key}} + return &RsaPublicKey{opensslPublicKey{key: sk.opensslPrivateKey.key}} } // UnmarshalRsaPrivateKey returns a private key from the input x509 bytes diff --git a/core/event/identify.go b/core/event/identify.go new file mode 100644 index 0000000000..7c4d1895fa --- /dev/null +++ b/core/event/identify.go @@ -0,0 +1,17 @@ +package event + +import "github.com/libp2p/go-libp2p-core/peer" + +// EvtPeerIdentificationCompleted is emitted when the initial identification round for a peer is completed. +type EvtPeerIdentificationCompleted struct { + // Peer is the ID of the peer whose identification succeeded. + Peer peer.ID +} + +// EvtPeerIdentificationFailed is emitted when the initial identification round for a peer failed. +type EvtPeerIdentificationFailed struct { + // Peer is the ID of the peer whose identification failed. + Peer peer.ID + // Reason is the reason why identification failed. + Reason error +} diff --git a/core/event/routability.go b/core/event/routability.go new file mode 100644 index 0000000000..7a25d69cc2 --- /dev/null +++ b/core/event/routability.go @@ -0,0 +1,21 @@ +package event + +// EvtLocalRoutabilityPrivate is an event struct to be emitted with the local's +// node routability changes to PRIVATE (i.e. not routable from the Internet). +// +// This event is usually emitted by the AutoNAT subsystem. +type EvtLocalRoutabilityPrivate struct{} + +// EvtLocalRoutabilityPublic is an event struct to be emitted with the local's +// node routability changes to PUBLIC (i.e. appear to routable from the +// Internet). +// +// This event is usually emitted by the AutoNAT subsystem. +type EvtLocalRoutabilityPublic struct{} + +// EvtLocalRoutabilityUnknown is an event struct to be emitted with the local's +// node routability changes to UNKNOWN (i.e. we were unable to make a +// determination about our NAT status with enough confidence). +// +// This event is usually emitted by the AutoNAT subsystem. +type EvtLocalRoutabilityUnknown struct{}