Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ipns): helper ValidateWithPeerID and UnmarshalIpnsEntry #294

Merged
merged 1 commit into from
May 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
})
}