Signed envelopes & routing records (#73)
* add SignedEnvelope type
* use struct for SignedEnvelope instead of exposing protobuf directly
* doc comments for envelopes
* tests for SignedEnvelopes
* add helpers to make routing records for Host
* fix doc comment
* go fmt
* add method to peerstore to retrieve signed routing records
* update to match spec changes
* just use nanoseconds
* use proto3 & rename fields to match spec changes
* use proto3 for routing records
* make envelope fields private & validate on unmarshal
* use buffer pool for envelope signatures
* tests for RoutingState
* go fmt
* rename Equals -> Equal, add some comments
* use test helpers
* get rid of unsigned RoutingState struct, only expose SignedRoutingState
* rm batching SignedRoutingStates accessor in peerstore
the datastore peerstore implementation doesn't support batched reads, so
it's no more efficient to get a bunch of states at once than it
is to call SignedRoutingState multiple times.
* whitespace
* expose struct fields & remove accessors
* use camelCase in protos for consistency
* use multiformats uvarint for length-prefixes
* remove payloadType check when unmarhaling
* rm stray ref to golang/protobuf
* define CertifiedAddrBook to avoid breaking API change
* add events for updated addresses and routing state
* remove SignedRoutingStateFromHost helper
moving this to go-libp2p
* add routing state records, extend peerstore API
* fix: rebuild protos with new gogofaster generator
* filter private addrs from signed routing records
* envelope: use byte slices from pool; adjust interface.
* move envelope to record package.
* move protobuf files; adjust imports everywhere.
* rename RoutingStateRecord -> PeerRecord
also removes embedded reference to Envelope from the record,
as that was confusing.
as a result, the CertifiedAddrBook now accepts/returns
record.SignedEnvelope instead of a specialized type.
* hoist Seq from PeerRecord to SignedEnvelope
* test that PeerRecords can't be signed by wrong key
* commit go.sum
* add Seq field to envelope signature
* fix proto_path in Makefile
* fix import ordering
* comments for PeerRecord proto message
also removes the seq field from PeerMessage proto,
since it was moved to the SignedEnvelope
* use Record type for envelope payloads
* rename SignedEnvelope -> Envelope, unmarshal payload in ConsumeEnvelope
* return buffer to pool before early return
* doc comments
* rename CertifiedAddrBook methods, update comments
* cache unmarshalled Record payload inside Envelope
* doc comments
* store reflect.Type when registering Record
* Revert "return buffer to pool before early return"
8d8da386f26482e06dc21989a6b5ade69f0a46d9
misread this - unsigned will be nil if there's an
error, so it was right the way it was
* use a DefaultRecord for unregistered PayloadTypes
instead of returning an error if we don't have a registered
Record for a given PayloadType, we can have a catch-all
DefaultRecord type that just preserves the original payload
as a []byte
* cleanup DefaultRecord code a bit
- removes unused error return from blankRecordForPayloadType
- just references instead of copying in DefaultRecord.UnmarshalRecord
I figure this is likely safe, since we'll be unmarshalling from the
payload of an Envelope, which shouldn't get altered after it's
created.
* use explicit payloadType in MakeEnvelopeWithRecord
* Revert DefaultRecord commits
ae3bc7bdfb657c232229229706854a56effca80b
a26c845a766b45ceabd87c17c0801d191650f0d4
* doc comments
* move Seq field back to PeerRecord
* make diffs optional in EvtLocalAddressesUpdated
* more envelope tests
* replace MakeEnvelope with record.Seal
also:
- add Domain and Codec fields to Record interface
* fix import
* add interface check
* rename ProcessPeerRecord -> ConsumePeerRecord
also, adds bool `accepted` return value
* rename event field, add doc comment
* peer record protobuf: fix field casing.
* record protobuf: add docs and fix casing.
* cleanup: group imports.
* nit: split test/utils.go => test/{addrs,errors}.go.
Co-authored-by: Raúl Kripalani <raul.kripalani@gmail.com>
2020-02-11 03:53:24 +08:00
|
|
|
package record_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"errors"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
crypto "github.com/libp2p/go-libp2p-core/crypto"
|
|
|
|
. "github.com/libp2p/go-libp2p-core/record"
|
|
|
|
pb "github.com/libp2p/go-libp2p-core/record/pb"
|
|
|
|
"github.com/libp2p/go-libp2p-core/test"
|
|
|
|
|
|
|
|
"github.com/gogo/protobuf/proto"
|
|
|
|
)
|
|
|
|
|
|
|
|
type simpleRecord struct {
|
|
|
|
testDomain *string
|
|
|
|
testCodec []byte
|
|
|
|
message string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *simpleRecord) Domain() string {
|
|
|
|
if r.testDomain != nil {
|
|
|
|
return *r.testDomain
|
|
|
|
}
|
|
|
|
return "libp2p-testing"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *simpleRecord) Codec() []byte {
|
|
|
|
if r.testCodec != nil {
|
|
|
|
return r.testCodec
|
|
|
|
}
|
|
|
|
return []byte("/libp2p/testdata")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *simpleRecord) MarshalRecord() ([]byte, error) {
|
|
|
|
return []byte(r.message), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *simpleRecord) UnmarshalRecord(buf []byte) error {
|
|
|
|
r.message = string(buf)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make an envelope, verify & open it, marshal & unmarshal it
|
|
|
|
func TestEnvelopeHappyPath(t *testing.T) {
|
|
|
|
var (
|
|
|
|
rec = &simpleRecord{message: "hello world!"}
|
|
|
|
priv, pub, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
|
|
|
)
|
|
|
|
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
payload, err := rec.MarshalRecord()
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
envelope, err := Seal(rec, priv)
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
if !envelope.PublicKey.Equals(pub) {
|
|
|
|
t.Error("envelope has unexpected public key")
|
|
|
|
}
|
|
|
|
|
2021-03-31 07:13:36 +08:00
|
|
|
if !bytes.Equal(rec.Codec(), envelope.PayloadType) {
|
Signed envelopes & routing records (#73)
* add SignedEnvelope type
* use struct for SignedEnvelope instead of exposing protobuf directly
* doc comments for envelopes
* tests for SignedEnvelopes
* add helpers to make routing records for Host
* fix doc comment
* go fmt
* add method to peerstore to retrieve signed routing records
* update to match spec changes
* just use nanoseconds
* use proto3 & rename fields to match spec changes
* use proto3 for routing records
* make envelope fields private & validate on unmarshal
* use buffer pool for envelope signatures
* tests for RoutingState
* go fmt
* rename Equals -> Equal, add some comments
* use test helpers
* get rid of unsigned RoutingState struct, only expose SignedRoutingState
* rm batching SignedRoutingStates accessor in peerstore
the datastore peerstore implementation doesn't support batched reads, so
it's no more efficient to get a bunch of states at once than it
is to call SignedRoutingState multiple times.
* whitespace
* expose struct fields & remove accessors
* use camelCase in protos for consistency
* use multiformats uvarint for length-prefixes
* remove payloadType check when unmarhaling
* rm stray ref to golang/protobuf
* define CertifiedAddrBook to avoid breaking API change
* add events for updated addresses and routing state
* remove SignedRoutingStateFromHost helper
moving this to go-libp2p
* add routing state records, extend peerstore API
* fix: rebuild protos with new gogofaster generator
* filter private addrs from signed routing records
* envelope: use byte slices from pool; adjust interface.
* move envelope to record package.
* move protobuf files; adjust imports everywhere.
* rename RoutingStateRecord -> PeerRecord
also removes embedded reference to Envelope from the record,
as that was confusing.
as a result, the CertifiedAddrBook now accepts/returns
record.SignedEnvelope instead of a specialized type.
* hoist Seq from PeerRecord to SignedEnvelope
* test that PeerRecords can't be signed by wrong key
* commit go.sum
* add Seq field to envelope signature
* fix proto_path in Makefile
* fix import ordering
* comments for PeerRecord proto message
also removes the seq field from PeerMessage proto,
since it was moved to the SignedEnvelope
* use Record type for envelope payloads
* rename SignedEnvelope -> Envelope, unmarshal payload in ConsumeEnvelope
* return buffer to pool before early return
* doc comments
* rename CertifiedAddrBook methods, update comments
* cache unmarshalled Record payload inside Envelope
* doc comments
* store reflect.Type when registering Record
* Revert "return buffer to pool before early return"
8d8da386f26482e06dc21989a6b5ade69f0a46d9
misread this - unsigned will be nil if there's an
error, so it was right the way it was
* use a DefaultRecord for unregistered PayloadTypes
instead of returning an error if we don't have a registered
Record for a given PayloadType, we can have a catch-all
DefaultRecord type that just preserves the original payload
as a []byte
* cleanup DefaultRecord code a bit
- removes unused error return from blankRecordForPayloadType
- just references instead of copying in DefaultRecord.UnmarshalRecord
I figure this is likely safe, since we'll be unmarshalling from the
payload of an Envelope, which shouldn't get altered after it's
created.
* use explicit payloadType in MakeEnvelopeWithRecord
* Revert DefaultRecord commits
ae3bc7bdfb657c232229229706854a56effca80b
a26c845a766b45ceabd87c17c0801d191650f0d4
* doc comments
* move Seq field back to PeerRecord
* make diffs optional in EvtLocalAddressesUpdated
* more envelope tests
* replace MakeEnvelope with record.Seal
also:
- add Domain and Codec fields to Record interface
* fix import
* add interface check
* rename ProcessPeerRecord -> ConsumePeerRecord
also, adds bool `accepted` return value
* rename event field, add doc comment
* peer record protobuf: fix field casing.
* record protobuf: add docs and fix casing.
* cleanup: group imports.
* nit: split test/utils.go => test/{addrs,errors}.go.
Co-authored-by: Raúl Kripalani <raul.kripalani@gmail.com>
2020-02-11 03:53:24 +08:00
|
|
|
t.Error("PayloadType does not match record Codec")
|
|
|
|
}
|
|
|
|
|
|
|
|
serialized, err := envelope.Marshal()
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
RegisterType(&simpleRecord{})
|
|
|
|
deserialized, rec2, err := ConsumeEnvelope(serialized, rec.Domain())
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
2021-03-31 07:13:36 +08:00
|
|
|
if !bytes.Equal(deserialized.RawPayload, payload) {
|
Signed envelopes & routing records (#73)
* add SignedEnvelope type
* use struct for SignedEnvelope instead of exposing protobuf directly
* doc comments for envelopes
* tests for SignedEnvelopes
* add helpers to make routing records for Host
* fix doc comment
* go fmt
* add method to peerstore to retrieve signed routing records
* update to match spec changes
* just use nanoseconds
* use proto3 & rename fields to match spec changes
* use proto3 for routing records
* make envelope fields private & validate on unmarshal
* use buffer pool for envelope signatures
* tests for RoutingState
* go fmt
* rename Equals -> Equal, add some comments
* use test helpers
* get rid of unsigned RoutingState struct, only expose SignedRoutingState
* rm batching SignedRoutingStates accessor in peerstore
the datastore peerstore implementation doesn't support batched reads, so
it's no more efficient to get a bunch of states at once than it
is to call SignedRoutingState multiple times.
* whitespace
* expose struct fields & remove accessors
* use camelCase in protos for consistency
* use multiformats uvarint for length-prefixes
* remove payloadType check when unmarhaling
* rm stray ref to golang/protobuf
* define CertifiedAddrBook to avoid breaking API change
* add events for updated addresses and routing state
* remove SignedRoutingStateFromHost helper
moving this to go-libp2p
* add routing state records, extend peerstore API
* fix: rebuild protos with new gogofaster generator
* filter private addrs from signed routing records
* envelope: use byte slices from pool; adjust interface.
* move envelope to record package.
* move protobuf files; adjust imports everywhere.
* rename RoutingStateRecord -> PeerRecord
also removes embedded reference to Envelope from the record,
as that was confusing.
as a result, the CertifiedAddrBook now accepts/returns
record.SignedEnvelope instead of a specialized type.
* hoist Seq from PeerRecord to SignedEnvelope
* test that PeerRecords can't be signed by wrong key
* commit go.sum
* add Seq field to envelope signature
* fix proto_path in Makefile
* fix import ordering
* comments for PeerRecord proto message
also removes the seq field from PeerMessage proto,
since it was moved to the SignedEnvelope
* use Record type for envelope payloads
* rename SignedEnvelope -> Envelope, unmarshal payload in ConsumeEnvelope
* return buffer to pool before early return
* doc comments
* rename CertifiedAddrBook methods, update comments
* cache unmarshalled Record payload inside Envelope
* doc comments
* store reflect.Type when registering Record
* Revert "return buffer to pool before early return"
8d8da386f26482e06dc21989a6b5ade69f0a46d9
misread this - unsigned will be nil if there's an
error, so it was right the way it was
* use a DefaultRecord for unregistered PayloadTypes
instead of returning an error if we don't have a registered
Record for a given PayloadType, we can have a catch-all
DefaultRecord type that just preserves the original payload
as a []byte
* cleanup DefaultRecord code a bit
- removes unused error return from blankRecordForPayloadType
- just references instead of copying in DefaultRecord.UnmarshalRecord
I figure this is likely safe, since we'll be unmarshalling from the
payload of an Envelope, which shouldn't get altered after it's
created.
* use explicit payloadType in MakeEnvelopeWithRecord
* Revert DefaultRecord commits
ae3bc7bdfb657c232229229706854a56effca80b
a26c845a766b45ceabd87c17c0801d191650f0d4
* doc comments
* move Seq field back to PeerRecord
* make diffs optional in EvtLocalAddressesUpdated
* more envelope tests
* replace MakeEnvelope with record.Seal
also:
- add Domain and Codec fields to Record interface
* fix import
* add interface check
* rename ProcessPeerRecord -> ConsumePeerRecord
also, adds bool `accepted` return value
* rename event field, add doc comment
* peer record protobuf: fix field casing.
* record protobuf: add docs and fix casing.
* cleanup: group imports.
* nit: split test/utils.go => test/{addrs,errors}.go.
Co-authored-by: Raúl Kripalani <raul.kripalani@gmail.com>
2020-02-11 03:53:24 +08:00
|
|
|
t.Error("payload of envelope does not match input")
|
|
|
|
}
|
|
|
|
|
|
|
|
if !envelope.Equal(deserialized) {
|
|
|
|
t.Error("round-trip serde results in unequal envelope structures")
|
|
|
|
}
|
|
|
|
|
|
|
|
typedRec, ok := rec2.(*simpleRecord)
|
|
|
|
if !ok {
|
|
|
|
t.Error("expected ConsumeEnvelope to return record with type registered for payloadType")
|
|
|
|
}
|
|
|
|
if typedRec.message != "hello world!" {
|
|
|
|
t.Error("unexpected alteration of record")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConsumeTypedEnvelope(t *testing.T) {
|
|
|
|
var (
|
|
|
|
rec = simpleRecord{message: "hello world!"}
|
|
|
|
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
|
|
|
)
|
|
|
|
|
|
|
|
envelope, err := Seal(&rec, priv)
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
envelopeBytes, err := envelope.Marshal()
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
rec2 := &simpleRecord{}
|
|
|
|
_, err = ConsumeTypedEnvelope(envelopeBytes, rec2)
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
if rec2.message != "hello world!" {
|
|
|
|
t.Error("unexpected alteration of record")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMakeEnvelopeFailsWithEmptyDomain(t *testing.T) {
|
|
|
|
var (
|
|
|
|
rec = simpleRecord{message: "hello world!"}
|
|
|
|
domain = ""
|
|
|
|
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// override domain with empty string
|
|
|
|
rec.testDomain = &domain
|
|
|
|
|
|
|
|
_, err = Seal(&rec, priv)
|
|
|
|
test.ExpectError(t, err, "making an envelope with an empty domain should fail")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMakeEnvelopeFailsWithEmptyPayloadType(t *testing.T) {
|
|
|
|
var (
|
|
|
|
rec = simpleRecord{message: "hello world!"}
|
|
|
|
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// override payload with empty slice
|
|
|
|
rec.testCodec = []byte{}
|
|
|
|
|
|
|
|
_, err = Seal(&rec, priv)
|
|
|
|
test.ExpectError(t, err, "making an envelope with an empty payloadType should fail")
|
|
|
|
}
|
|
|
|
|
|
|
|
type failingRecord struct {
|
|
|
|
allowMarshal bool
|
|
|
|
allowUnmarshal bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r failingRecord) Domain() string {
|
|
|
|
return "testing"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r failingRecord) Codec() []byte {
|
|
|
|
return []byte("doesn't matter")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r failingRecord) MarshalRecord() ([]byte, error) {
|
|
|
|
if r.allowMarshal {
|
|
|
|
return []byte{}, nil
|
|
|
|
}
|
|
|
|
return nil, errors.New("marshal failed")
|
|
|
|
}
|
|
|
|
func (r failingRecord) UnmarshalRecord(data []byte) error {
|
|
|
|
if r.allowUnmarshal {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return errors.New("unmarshal failed")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSealFailsIfRecordMarshalFails(t *testing.T) {
|
|
|
|
var (
|
|
|
|
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
rec := failingRecord{}
|
|
|
|
_, err = Seal(rec, priv)
|
|
|
|
test.ExpectError(t, err, "Seal should fail if Record fails to marshal")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConsumeEnvelopeFailsIfEnvelopeUnmarshalFails(t *testing.T) {
|
|
|
|
_, _, err := ConsumeEnvelope([]byte("not an Envelope protobuf"), "doesn't-matter")
|
|
|
|
test.ExpectError(t, err, "ConsumeEnvelope should fail if Envelope fails to unmarshal")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConsumeEnvelopeFailsIfRecordUnmarshalFails(t *testing.T) {
|
|
|
|
var (
|
|
|
|
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
RegisterType(failingRecord{})
|
|
|
|
rec := failingRecord{allowMarshal: true}
|
|
|
|
env, err := Seal(rec, priv)
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
envBytes, err := env.Marshal()
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
_, _, err = ConsumeEnvelope(envBytes, rec.Domain())
|
|
|
|
test.ExpectError(t, err, "ConsumeEnvelope should fail if Record fails to unmarshal")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConsumeTypedEnvelopeFailsIfRecordUnmarshalFails(t *testing.T) {
|
|
|
|
var (
|
|
|
|
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
RegisterType(failingRecord{})
|
|
|
|
rec := failingRecord{allowMarshal: true}
|
|
|
|
env, err := Seal(rec, priv)
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
envBytes, err := env.Marshal()
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
rec2 := failingRecord{}
|
|
|
|
_, err = ConsumeTypedEnvelope(envBytes, rec2)
|
|
|
|
test.ExpectError(t, err, "ConsumeTypedEnvelope should fail if Record fails to unmarshal")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEnvelopeValidateFailsForDifferentDomain(t *testing.T) {
|
|
|
|
var (
|
|
|
|
rec = &simpleRecord{message: "hello world"}
|
|
|
|
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
|
|
|
)
|
|
|
|
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
envelope, err := Seal(rec, priv)
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
serialized, err := envelope.Marshal()
|
2021-03-31 07:13:36 +08:00
|
|
|
test.AssertNilError(t, err)
|
Signed envelopes & routing records (#73)
* add SignedEnvelope type
* use struct for SignedEnvelope instead of exposing protobuf directly
* doc comments for envelopes
* tests for SignedEnvelopes
* add helpers to make routing records for Host
* fix doc comment
* go fmt
* add method to peerstore to retrieve signed routing records
* update to match spec changes
* just use nanoseconds
* use proto3 & rename fields to match spec changes
* use proto3 for routing records
* make envelope fields private & validate on unmarshal
* use buffer pool for envelope signatures
* tests for RoutingState
* go fmt
* rename Equals -> Equal, add some comments
* use test helpers
* get rid of unsigned RoutingState struct, only expose SignedRoutingState
* rm batching SignedRoutingStates accessor in peerstore
the datastore peerstore implementation doesn't support batched reads, so
it's no more efficient to get a bunch of states at once than it
is to call SignedRoutingState multiple times.
* whitespace
* expose struct fields & remove accessors
* use camelCase in protos for consistency
* use multiformats uvarint for length-prefixes
* remove payloadType check when unmarhaling
* rm stray ref to golang/protobuf
* define CertifiedAddrBook to avoid breaking API change
* add events for updated addresses and routing state
* remove SignedRoutingStateFromHost helper
moving this to go-libp2p
* add routing state records, extend peerstore API
* fix: rebuild protos with new gogofaster generator
* filter private addrs from signed routing records
* envelope: use byte slices from pool; adjust interface.
* move envelope to record package.
* move protobuf files; adjust imports everywhere.
* rename RoutingStateRecord -> PeerRecord
also removes embedded reference to Envelope from the record,
as that was confusing.
as a result, the CertifiedAddrBook now accepts/returns
record.SignedEnvelope instead of a specialized type.
* hoist Seq from PeerRecord to SignedEnvelope
* test that PeerRecords can't be signed by wrong key
* commit go.sum
* add Seq field to envelope signature
* fix proto_path in Makefile
* fix import ordering
* comments for PeerRecord proto message
also removes the seq field from PeerMessage proto,
since it was moved to the SignedEnvelope
* use Record type for envelope payloads
* rename SignedEnvelope -> Envelope, unmarshal payload in ConsumeEnvelope
* return buffer to pool before early return
* doc comments
* rename CertifiedAddrBook methods, update comments
* cache unmarshalled Record payload inside Envelope
* doc comments
* store reflect.Type when registering Record
* Revert "return buffer to pool before early return"
8d8da386f26482e06dc21989a6b5ade69f0a46d9
misread this - unsigned will be nil if there's an
error, so it was right the way it was
* use a DefaultRecord for unregistered PayloadTypes
instead of returning an error if we don't have a registered
Record for a given PayloadType, we can have a catch-all
DefaultRecord type that just preserves the original payload
as a []byte
* cleanup DefaultRecord code a bit
- removes unused error return from blankRecordForPayloadType
- just references instead of copying in DefaultRecord.UnmarshalRecord
I figure this is likely safe, since we'll be unmarshalling from the
payload of an Envelope, which shouldn't get altered after it's
created.
* use explicit payloadType in MakeEnvelopeWithRecord
* Revert DefaultRecord commits
ae3bc7bdfb657c232229229706854a56effca80b
a26c845a766b45ceabd87c17c0801d191650f0d4
* doc comments
* move Seq field back to PeerRecord
* make diffs optional in EvtLocalAddressesUpdated
* more envelope tests
* replace MakeEnvelope with record.Seal
also:
- add Domain and Codec fields to Record interface
* fix import
* add interface check
* rename ProcessPeerRecord -> ConsumePeerRecord
also, adds bool `accepted` return value
* rename event field, add doc comment
* peer record protobuf: fix field casing.
* record protobuf: add docs and fix casing.
* cleanup: group imports.
* nit: split test/utils.go => test/{addrs,errors}.go.
Co-authored-by: Raúl Kripalani <raul.kripalani@gmail.com>
2020-02-11 03:53:24 +08:00
|
|
|
|
|
|
|
// try to open our modified envelope
|
|
|
|
_, _, err = ConsumeEnvelope(serialized, "wrong-domain")
|
|
|
|
test.ExpectError(t, err, "should not be able to open envelope with incorrect domain")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEnvelopeValidateFailsIfPayloadTypeIsAltered(t *testing.T) {
|
|
|
|
var (
|
|
|
|
rec = &simpleRecord{message: "hello world!"}
|
|
|
|
domain = "libp2p-testing"
|
|
|
|
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
|
|
|
)
|
|
|
|
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
envelope, err := Seal(rec, priv)
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
serialized := alterMessageAndMarshal(t, envelope, func(msg *pb.Envelope) {
|
|
|
|
msg.PayloadType = []byte("foo")
|
|
|
|
})
|
|
|
|
|
|
|
|
// try to open our modified envelope
|
|
|
|
_, _, err = ConsumeEnvelope(serialized, domain)
|
|
|
|
test.ExpectError(t, err, "should not be able to open envelope with modified PayloadType")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEnvelopeValidateFailsIfContentsAreAltered(t *testing.T) {
|
|
|
|
var (
|
|
|
|
rec = &simpleRecord{message: "hello world!"}
|
|
|
|
domain = "libp2p-testing"
|
|
|
|
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
|
|
|
)
|
|
|
|
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
envelope, err := Seal(rec, priv)
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
serialized := alterMessageAndMarshal(t, envelope, func(msg *pb.Envelope) {
|
|
|
|
msg.Payload = []byte("totally legit, trust me")
|
|
|
|
})
|
|
|
|
|
|
|
|
// try to open our modified envelope
|
|
|
|
_, _, err = ConsumeEnvelope(serialized, domain)
|
|
|
|
test.ExpectError(t, err, "should not be able to open envelope with modified payload")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Since we're outside of the crypto package (to avoid import cycles with test package),
|
|
|
|
// we can't alter the fields in a Envelope directly. This helper marshals
|
|
|
|
// the envelope to a protobuf and calls the alterMsg function, which should
|
|
|
|
// alter the protobuf message.
|
|
|
|
// Returns the serialized altered protobuf message.
|
|
|
|
func alterMessageAndMarshal(t *testing.T, envelope *Envelope, alterMsg func(*pb.Envelope)) []byte {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
serialized, err := envelope.Marshal()
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
msg := pb.Envelope{}
|
|
|
|
err = proto.Unmarshal(serialized, &msg)
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
alterMsg(&msg)
|
|
|
|
serialized, err = msg.Marshal()
|
|
|
|
test.AssertNilError(t, err)
|
|
|
|
|
|
|
|
return serialized
|
|
|
|
}
|