From cf5618c2114f9b4aa8af8e31b4d02253a29d3518 Mon Sep 17 00:00:00 2001 From: Justin Drake Date: Wed, 28 Jun 2017 11:18:45 +0100 Subject: [PATCH] Do not publish public keys extractable from ID (with tests) License: MIT Signed-off-by: Justin Drake --- namesys/publisher.go | 18 ++++-- namesys/publisher_test.go | 115 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 6 deletions(-) create mode 100644 namesys/publisher_test.go diff --git a/namesys/publisher.go b/namesys/publisher.go index c902076491f..05a18cd95c4 100644 --- a/namesys/publisher.go +++ b/namesys/publisher.go @@ -150,18 +150,24 @@ func PutRecordToRouting(ctx context.Context, k ci.PrivKey, value path.Path, seqn entry.Ttl = proto.Uint64(uint64(ttl.Nanoseconds())) } - errs := make(chan error, 2) + errs := make(chan error, 2) // At most two errors (IPNS, and public key) + + // Attempt to extract the public key from the ID + extractedPublicKey := id.ExtractPublicKey() go func() { errs <- PublishEntry(ctx, r, ipnskey, entry) }() - go func() { - errs <- PublishPublicKey(ctx, r, namekey, k.GetPublic()) - }() + // Publish the public key if a public key cannot be extracted from the ID + if extractedPublicKey == nil { + go func() { + errs <- PublishPublicKey(ctx, r, namekey, k.GetPublic()) + }() - if err := waitOnErrChan(ctx, errs); err != nil { - return err + if err := waitOnErrChan(ctx, errs); err != nil { + return err + } } return waitOnErrChan(ctx, errs) diff --git a/namesys/publisher_test.go b/namesys/publisher_test.go new file mode 100644 index 00000000000..53cf22a6215 --- /dev/null +++ b/namesys/publisher_test.go @@ -0,0 +1,115 @@ +package namesys + +import ( + "context" + "crypto/rand" + "testing" + "time" + + path "github.com/ipfs/go-ipfs/path" + mockrouting "github.com/ipfs/go-ipfs/routing/mock" + dshelp "github.com/ipfs/go-ipfs/thirdparty/ds-help" + testutil "github.com/ipfs/go-ipfs/thirdparty/testutil" + + ds "gx/ipfs/QmVSase1JP7cq9QkPT46oNwdp9pT6kBkG3oqS14y3QcZjG/go-datastore" + dssync "gx/ipfs/QmVSase1JP7cq9QkPT46oNwdp9pT6kBkG3oqS14y3QcZjG/go-datastore/sync" + ma "gx/ipfs/QmXY77cVe7rVRQXZZQRioukUM7aRW3BTcAgJe12MCtb3Ji/go-multiaddr" + peer "gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer" + ci "gx/ipfs/QmaPbCnUMBohSGo3KnxEa2bHqyJVVeEEcwtqJAYxerieBo/go-libp2p-crypto" +) + +type identity struct { + testutil.PeerNetParams +} + +func (p *identity) ID() peer.ID { + return p.PeerNetParams.ID +} + +func (p *identity) Address() ma.Multiaddr { + return p.Addr +} + +func (p *identity) PrivateKey() ci.PrivKey { + return p.PrivKey +} + +func (p *identity) PublicKey() ci.PubKey { + return p.PubKey +} + +func testNamekeyPublisher(t *testing.T, keyType int, expectedErr error, expectedExistence bool) { + // Context + ctx := context.Background() + + // Private key + privKey, pubKey, err := ci.GenerateKeyPairWithReader(keyType, 2048, rand.Reader) + if err != nil { + t.Fatal(err) + } + + // ID + var id peer.ID + switch keyType { + case ci.Ed25519: + id, err = peer.IDFromEd25519PublicKey(pubKey) + default: + id, err = peer.IDFromPublicKey(pubKey) + } + + if err != nil { + t.Fatal(err) + } + + // Value + value := path.Path("ipfs/TESTING") + + // Seqnum + seqnum := uint64(0) + + // Eol + eol := time.Now().Add(24 * time.Hour) + + // Routing value store + p := testutil.PeerNetParams{ + ID: id, + PrivKey: privKey, + PubKey: pubKey, + Addr: testutil.ZeroLocalTCPAddress, + } + + dstore := dssync.MutexWrap(ds.NewMapDatastore()) + serv := mockrouting.NewServer() + r := serv.ClientWithDatastore(context.Background(), &identity{p}, dstore) + + err = PutRecordToRouting(ctx, privKey, value, seqnum, eol, r, id) + if err != nil { + t.Fatal(err) + } + + // Check for namekey existence in value store + namekey, _ := IpnsKeysForID(id) + _, err = r.GetValue(ctx, namekey) + if err != expectedErr { + t.Fatal(err) + } + + // Also check datastore for completeness + key := dshelp.NewKeyFromBinary([]byte(namekey)) + exists, err := dstore.Has(key) + if err != nil { + t.Fatal(err) + } + + if exists != expectedExistence { + t.Fatal("Unexpected key existence in datastore") + } +} + +func TestRSAPublisher(t *testing.T) { + testNamekeyPublisher(t, ci.RSA, nil, true) +} + +func TestEd22519Publisher(t *testing.T) { + testNamekeyPublisher(t, ci.Ed25519, ds.ErrNotFound, false) +}