Skip to content

Commit

Permalink
feat(ipns): helper ValidateWithPeerID and UnmarshalIpnsEntry (#294)
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias authored May 10, 2023
1 parent dc731ca commit 33e3f0c
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 6 deletions.
6 changes: 2 additions & 4 deletions gateway/handler_ipns_record.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ import (
"time"

"github.com/cespare/xxhash/v2"
"github.com/gogo/protobuf/proto"
ipath "github.com/ipfs/boxo/coreiface/path"
ipns_pb "github.com/ipfs/boxo/ipns/pb"
"github.com/ipfs/boxo/ipns"
"github.com/ipfs/go-cid"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
Expand Down Expand Up @@ -50,8 +49,7 @@ func (i *handler) serveIpnsRecord(ctx context.Context, w http.ResponseWriter, r
return false
}

var record ipns_pb.IpnsEntry
err = proto.Unmarshal(rawRecord, &record)
record, err := ipns.UnmarshalIpnsEntry(rawRecord)
if err != nil {
webError(w, err, http.StatusInternalServerError)
return false
Expand Down
21 changes: 21 additions & 0 deletions ipns/ipns.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ func createCborDataForIpnsEntry(e *pb.IpnsEntry) ([]byte, error) {
return buf.Bytes(), nil
}

// ValidateWithPeerID validates the given IPNS entry against the given peer ID.
func ValidateWithPeerID(pid peer.ID, entry *pb.IpnsEntry) error {
pk, err := ExtractPublicKey(pid, entry)
if err != nil {
return err
}

return Validate(pk, entry)
}

// 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
Expand Down Expand Up @@ -287,6 +297,17 @@ func EmbedPublicKey(pk ic.PubKey, entry *pb.IpnsEntry) error {
return nil
}

// UnmarshalIpnsEntry unmarshalls an IPNS entry from a slice of bytes.
func UnmarshalIpnsEntry(data []byte) (*pb.IpnsEntry, error) {
var entry pb.IpnsEntry
err := proto.Unmarshal(data, &entry)
if err != nil {
return nil, err
}

return &entry, nil
}

// ExtractPublicKey extracts a public key matching `pid` from the IPNS record,
// if possible.
//
Expand Down
38 changes: 36 additions & 2 deletions ipns/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
pstore "github.com/libp2p/go-libp2p/core/peerstore"
"github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoremem"
"github.com/multiformats/go-multicodec"
"github.com/stretchr/testify/assert"
)

func testValidatorCase(t *testing.T, priv crypto.PrivKey, kbook pstore.KeyBook, key string, val []byte, eol time.Time, exp error) {
Expand Down Expand Up @@ -143,8 +144,6 @@ func TestEmbeddedPubKeyValidate(t *testing.T) {
}

func TestPeerIDPubKeyValidate(t *testing.T) {
t.Skip("disabled until libp2p/go-libp2p-crypto#51 is fixed")

goodeol := time.Now().Add(time.Hour)
kbook, err := pstoremem.NewPeerstore()
if err != nil {
Expand Down Expand Up @@ -413,3 +412,38 @@ func genKeys(t *testing.T) (crypto.PrivKey, peer.ID, string) {

return priv, pid, ipnsKey
}

func TestValidateWithPeerID(t *testing.T) {
path := []byte("/ipfs/bafkreifjjcie6lypi6ny7amxnfftagclbuxndqonfipmb64f2km2devei4")
eol := time.Now().Add(time.Hour)

rnd := rand.New(rand.NewSource(42))

sk, pk, err := crypto.GenerateEd25519Key(rnd)
assert.NoError(t, err)

pid, err := peer.IDFromPublicKey(pk)
assert.NoError(t, err)

entry, err := Create(sk, path, 1, eol, 0)
assert.NoError(t, err)

t.Run("valid peer ID", func(t *testing.T) {
t.Parallel()
err = ValidateWithPeerID(pid, entry)
assert.NoError(t, err)
})

t.Run("invalid peer ID", func(t *testing.T) {
t.Parallel()

_, pk2, err := crypto.GenerateEd25519Key(rnd)
assert.NoError(t, err)

pid2, err := peer.IDFromPublicKey(pk2)
assert.NoError(t, err)

err = ValidateWithPeerID(pid2, entry)
assert.ErrorIs(t, err, ErrSignature)
})
}

0 comments on commit 33e3f0c

Please sign in to comment.