From e5d96b34e49b2e60e6dd9985b607185d3be4f7e5 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Tue, 20 Sep 2022 23:50:44 +0200 Subject: [PATCH] fix: MaxRecordSize of 10 KiB See rationale: https://github.com/ipfs/specs/pull/319#discussion_r968304911 --- errors.go | 7 +++++++ ipns.go | 5 +++++ validate_test.go | 20 ++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/errors.go b/errors.go index ebcd4e2..d78aaff 100644 --- a/errors.go +++ b/errors.go @@ -35,3 +35,10 @@ var ErrPublicKeyMismatch = errors.New("public key in record did not match expect // ErrBadRecord should be returned when an ipns record cannot be unmarshalled var ErrBadRecord = errors.New("record could not be unmarshalled") + +// 10 KiB limit defined in https://github.com/ipfs/specs/pull/319 +const MaxRecordSize int = 10 << (10 * 1) + +// ErrRecordSize should be returned when an ipns record is +// invalid due to being too big +var ErrRecordSize = errors.New("record exceeds allowed size limit") diff --git a/ipns.go b/ipns.go index fae3f6e..8782356 100644 --- a/ipns.go +++ b/ipns.go @@ -132,6 +132,11 @@ func createCborDataForIpnsEntry(e *pb.IpnsEntry) ([]byte, error) { // Validates validates the given IPNS entry against the given public key. func Validate(pk ic.PubKey, entry *pb.IpnsEntry) error { + // Make sure max size is respected + if entry.Size() > MaxRecordSize { + return ErrRecordSize + } + // Check the ipns record signature with the public key if entry.GetSignatureV2() == nil { // always error if no valid signature could be found diff --git a/validate_test.go b/validate_test.go index a0d7f7e..0b38329 100644 --- a/validate_test.go +++ b/validate_test.go @@ -274,6 +274,26 @@ func TestSignatureV1Ignored(t *testing.T) { } } +func TestMaxSizeValidate(t *testing.T) { + goodeol := time.Now().Add(time.Hour) + + sk, pk, err := crypto.GenerateEd25519Key(rand.New(rand.NewSource(42))) + if err != nil { + t.Fatal(err) + } + + // Create record over the max size (value+other fields) + value := make([]byte, MaxRecordSize) + entry, err := Create(sk, value, 1, goodeol, 0) + if err != nil { + t.Fatal(err) + } + // Must fail with ErrRecordSize + if err := Validate(pk, entry); !errors.Is(err, ErrRecordSize) { + t.Fatal(err) + } +} + func TestCborDataCanonicalization(t *testing.T) { goodeol := time.Now().Add(time.Hour)