Skip to content
This repository has been archived by the owner on Feb 12, 2024. It is now read-only.

fix: validate ipns records with inline public keys #3224

Merged
merged 5 commits into from
Aug 18, 2020
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
2 changes: 1 addition & 1 deletion packages/interface-ipfs-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"dirty-chai": "^2.0.1",
"ipfs-unixfs": "^1.0.3",
"ipfs-unixfs-importer": "^2.0.2",
"ipfs-utils": "^2.2.2",
"ipfs-utils": "^3.0.0",
"ipld-block": "^0.9.2",
"ipld-dag-cbor": "^0.16.0",
"ipld-dag-pb": "^0.19.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/ipfs-core-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"buffer": "^5.6.0",
"cids": "^0.8.3",
"err-code": "^2.0.0",
"ipfs-utils": "^2.2.2",
"ipfs-utils": "^3.0.0",
"it-all": "^1.0.1",
"it-map": "^1.0.0",
"it-peekable": "0.0.1"
Expand Down
2 changes: 1 addition & 1 deletion packages/ipfs-http-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"debug": "^4.1.0",
"form-data": "^3.0.0",
"ipfs-core-utils": "^0.3.1",
"ipfs-utils": "^2.2.2",
"ipfs-utils": "^3.0.0",
"ipld-block": "^0.9.2",
"ipld-dag-cbor": "^0.16.0",
"ipld-dag-pb": "^0.19.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/ipfs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
"ipfs-unixfs": "^1.0.3",
"ipfs-unixfs-exporter": "^2.0.2",
"ipfs-unixfs-importer": "^2.0.2",
"ipfs-utils": "^2.2.2",
"ipfs-utils": "^3.0.0",
"ipld": "^0.26.2",
"ipld-bitcoin": "^0.3.0",
"ipld-block": "^0.9.2",
Expand Down
30 changes: 1 addition & 29 deletions packages/ipfs/src/core/ipns/resolver.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict'

const ipns = require('ipns')
const crypto = require('libp2p-crypto')
const PeerId = require('peer-id')
const errcode = require('err-code')
const debug = require('debug')
Expand Down Expand Up @@ -99,34 +98,7 @@ class IpnsResolver {
throw errcode(new Error('found ipns record that we couldn\'t convert to a value'), 'ERR_INVALID_RECORD_RECEIVED')
}

// if the record has a public key validate it
if (ipnsEntry.pubKey) {
return this._validateRecord(peerId, ipnsEntry)
}

// Otherwise, try to get the public key from routing
let pubKey
try {
pubKey = await this._routing.get(routingKey.toBuffer())
} catch (err) {
log.error(err)

if (err.code === ERR_NOT_FOUND) {
throw errcode(new Error(`public key requested for ${name} was not found in the network`), 'ERR_NO_RECORD_FOUND')
}

throw errcode(new Error(`unexpected error getting the public key for the ipns record ${peerId.id}`), 'ERR_UNEXPECTED_ERROR_GETTING_PUB_KEY')
}

try {
// Insert it into the peer id, in order to be validated by IPNS validator
peerId.pubKey = crypto.keys.unmarshalPublicKey(pubKey)
} catch (err) {
log.error(err)

throw errcode(new Error('found public key record that we couldn\'t convert to a value'), 'ERR_INVALID_PUB_KEY_RECEIVED')
}

// We should have the public key by now (inline, or in the entry)
return this._validateRecord(peerId, ipnsEntry)
}

Expand Down
11 changes: 8 additions & 3 deletions packages/ipfs/test/core/name-pubsub.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
/* eslint-env mocha */
'use strict'

const { nanoid } = require('nanoid')
const { Buffer } = require('buffer')
const { expect } = require('interface-ipfs-core/src/utils/mocha')
const base64url = require('base64url')
Expand All @@ -18,6 +17,12 @@ const factory = require('../utils/factory')
const namespace = '/record/'
const ipfsRef = '/ipfs/QmPFVLPmp9zv5Z5KUqLhe2EivAGccQW2r7M7jhVJGLZoZU'

const daemonsOptions = {
ipfsOptions: {
EXPERIMENTAL: { ipnsPubsub: true }
}
}

describe('name-pubsub', function () {
const df = factory()
// TODO make this work in the browser and between daemon and in-proc in nodes
Expand All @@ -33,8 +38,8 @@ describe('name-pubsub', function () {
this.timeout(40 * 1000)

nodes = await Promise.all([
df.spawn({ type: 'proc', ipfsOptions: { pass: nanoid(), EXPERIMENTAL: { ipnsPubsub: true } } }),
df.spawn({ type: 'proc', ipfsOptions: { pass: nanoid(), EXPERIMENTAL: { ipnsPubsub: true } } })
df.spawn({ ...daemonsOptions }),
df.spawn({ ...daemonsOptions })
])

nodeA = nodes[0].api
Expand Down
15 changes: 15 additions & 0 deletions packages/ipfs/test/core/name.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const { Key } = require('interface-datastore')
const last = require('it-last')
const PeerId = require('peer-id')
const errCode = require('err-code')
const ipns = require('ipns')
const getIpnsRoutingConfig = require('../../src/core/ipns/routing/config')
const IpnsPublisher = require('../../src/core/ipns/publisher')
const IpnsRepublisher = require('../../src/core/ipns/republisher')
Expand Down Expand Up @@ -199,6 +200,20 @@ describe('name', function () {
})

describe('resolver', () => {
it('should resolve an inlined public key', async () => {
const peerId = await PeerId.create({ keyType: 'ed25519' })
const value = `/ipfs/${peerId.toB58String()}`
const record = await ipns.create(peerId.privKey, value, 1, 10e3)

const routing = {
get: sinon.stub().returns(ipns.marshal(record))
}
const resolver = new IpnsResolver(routing)

const resolved = await resolver.resolve(`/ipns/${peerId.toB58String()}`)
expect(resolved).to.equal(value)
})

it('should fail to resolve if the received name is not a string', () => {
const resolver = new IpnsResolver()
return expect(resolver.resolve(false))
Expand Down