From 192e5b8bffdcdca9856456eccd5cb1c01eee267d Mon Sep 17 00:00:00 2001 From: Friedel Ziegelmayer Date: Tue, 13 Sep 2016 14:43:54 +0200 Subject: [PATCH 01/11] refactor: make import and creation async This allows the use of native key generation in the browser BREAKING CHANGE: This changes the interface of .create, .createFromPrivKey, .createFromPubKey, .createFromJSON --- README.md | 35 ++++++--- src/index.js | 27 ++++--- test/index.spec.js | 182 +++++++++++++++++++++++++++++---------------- 3 files changed, 160 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index 7fc5deb..e5f121b 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,11 @@ to the multihash for ID generation.* var PeerId = require('peer-id') var bs58 = require('bs58') -var id = PeerId.create({ bits: 32 }) - -console.log('id ', id.toB58String()) -console.log('priv key ', bs58.encode(id.privKey.bytes)) -console.log('pub key ', bs58.encode(id.pubKey.bytes)) +PeerId.create({ bits: 512 }, (err, id) => { + console.log('id ', id.toB58String()) + console.log('priv key ', bs58.encode(id.privKey.bytes)) + console.log('pub key ', bs58.encode(id.pubKey.bytes)) +}) ``` ``` @@ -93,11 +93,14 @@ const PeerId = require('peer-id') The key format is detailed in [libp2p-crypto](https://github.com/libp2p/js-libp2p-crypto). -### `create([opts])` +### `create([opts], cb)` Generates a new Peer ID, complete with public/private keypair. - `opts: Object`: Default: `{bits: 2048}` +- `cb: Function` + +Calls back `cb` with `err, id`. ## Import @@ -112,20 +115,30 @@ Creates a Peer ID from a buffer representing the key's multihash. ### `createFromB58String(str)` Creates a Peer ID from a Base58 string representing the key's multihash. -### `createFromPubKey(pubKey)` +### `createFromPubKey(pubKey, cb)` + +- `publicKey: Buffer` +- `cb: Function` + +Creates a Peer ID from a buffer containing a public key and +calls back `cb` with `err, id`. -Creates a Peer ID from a buffer containing a public key. +### `createFromPrivKey(privKey, cb)` -### `createFromPrivKey(privKey)` +- `privKey: Buffer` +- `cb: Function` -Creates a Peer ID from a buffer containing a private key. +Creates a Peer ID from a buffer containing a private key and +calls back `cb` with `err, id`. -### `createFromJSON(obj)` +### `createFromJSON(obj, cb)` - `obj.id: String` - The multihash encoded in `base58` - `obj.pubKey: String` - The public key in protobuf format, encoded in 'base64' - `obj.privKey: String` - The private key in protobuf format, encoded in 'base 64' +- `cb: Function` +Calls back `cb` with `err, id`. ## Export diff --git a/src/index.js b/src/index.js index 7c58b4a..bfd300b 100644 --- a/src/index.js +++ b/src/index.js @@ -88,13 +88,21 @@ exports = module.exports = PeerId exports.Buffer = Buffer // generation -exports.create = function (opts) { +exports.create = function (opts, cb) { + if (typeof opts === 'function') { + cb = opts + opts = {} + } opts = opts || {} opts.bits = opts.bits || 2048 - const privKey = crypto.generateKeyPair('RSA', opts.bits) + crypto.generateKeyPair('RSA', opts.bits, (err, privKey) => { + if (err) { + return cb(err) + } - return new PeerId(privKey.public.hash(), privKey) + cb(null, new PeerId(privKey.public.hash(), privKey)) + }) } exports.createFromHexString = function (str) { @@ -110,27 +118,28 @@ exports.createFromB58String = function (str) { } // Public Key input will be a buffer -exports.createFromPubKey = function (key) { +exports.createFromPubKey = function (key, cb) { let buf = key if (typeof buf === 'string') { buf = new Buffer(key, 'base64') } + const pubKey = crypto.unmarshalPublicKey(buf) - return new PeerId(pubKey.hash(), null, pubKey) + cb(null, new PeerId(pubKey.hash(), null, pubKey)) } // Private key input will be a string -exports.createFromPrivKey = function (key) { +exports.createFromPrivKey = function (key, cb) { let buf = key if (typeof buf === 'string') { buf = new Buffer(key, 'base64') } const privKey = crypto.unmarshalPrivateKey(buf) - return new PeerId(privKey.public.hash(), privKey) + cb(null, new PeerId(privKey.public.hash(), privKey)) } -exports.createFromJSON = function (obj) { +exports.createFromJSON = function (obj, cb) { let priv let pub @@ -142,7 +151,7 @@ exports.createFromJSON = function (obj) { pub = crypto.unmarshalPublicKey(new Buffer(obj.pubKey, 'base64')) } - return new PeerId(mh.fromB58String(obj.id), priv, pub) + cb(null, new PeerId(mh.fromB58String(obj.id), priv, pub)) } function toB64Opt (val) { diff --git a/test/index.spec.js b/test/index.spec.js index 233a5ed..ba41d36 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -1,3 +1,4 @@ +/* eslint max-nested-callbacks: ["error", 8] */ /* eslint-env mocha */ 'use strict' @@ -19,9 +20,12 @@ describe('PeerId', () => { expect(PeerId).to.throw(Error) }) - it('create a new id', () => { - const id = PeerId.create() - expect(id.toB58String().length).to.equal(46) + it('create a new id', (done) => { + PeerId.create((err, id) => { + expect(err).to.not.exist + expect(id.toB58String().length).to.equal(46) + done() + }) }) it('recreate an Id from Hex string', () => { @@ -39,38 +43,61 @@ describe('PeerId', () => { expect(testIdB58String).to.equal(id.toB58String()) }) - it('Recreate from a Public Key', () => { - const id = PeerId.createFromPubKey(testId.pubKey) - expect(testIdB58String).to.equal(id.toB58String()) + it('Recreate from a Public Key', (done) => { + PeerId.createFromPubKey(testId.pubKey, (err, id) => { + expect(err).to.not.exist + expect(testIdB58String).to.equal(id.toB58String()) + done() + }) }) - it('Recreate from a Private Key', () => { - const id = PeerId.createFromPrivKey(testId.privKey) - expect(testIdB58String).to.equal(id.toB58String()) - - const id2 = PeerId.createFromPrivKey(new Buffer(testId.privKey, 'base64')) - expect(testIdB58String).to.equal(id2.toB58String()) + it('Recreate from a Private Key', (done) => { + PeerId.createFromPrivKey(testId.privKey, (err, id) => { + expect(err).to.not.exist + expect(testIdB58String).to.equal(id.toB58String()) + + const encoded = new Buffer(testId.privKey, 'base64') + PeerId.createFromPrivKey(encoded, (err, id2) => { + expect(err).to.not.exist + expect(testIdB58String).to.equal(id2.toB58String()) + done() + }) + }) }) - it('Compare generated ID with one created from PubKey', () => { - const id1 = PeerId.create() - const id2 = PeerId.createFromPubKey(id1.marshalPubKey()) - expect(id1.id).to.be.eql(id2.id) + it('Compare generated ID with one created from PubKey', (done) => { + PeerId.create((err, id1) => { + expect(err).to.not.exist + + PeerId.createFromPubKey(id1.marshalPubKey(), (err, id2) => { + expect(err).to.not.exist + expect(id1.id).to.be.eql(id2.id) + done() + }) + }) }) - it('Non-default # of bits', () => { - const shortId = PeerId.create({ bits: 128 }) - const longId = PeerId.create({ bits: 256 }) - expect(shortId.privKey.bytes.length).is.below(longId.privKey.bytes.length) + it('Non-default # of bits', (done) => { + PeerId.create({ bits: 512 }, (err, shortId) => { + expect(err).to.not.exist + PeerId.create({ bits: 1024 }, (err, longId) => { + expect(err).to.not.exist + expect(shortId.privKey.bytes.length).is.below(longId.privKey.bytes.length) + done() + }) + }) }) - it('Pretty printing', () => { - const id = PeerId.createFromPrivKey(testId.privKey) - const out = id.toPrint() + it('Pretty printing', (done) => { + PeerId.createFromPrivKey(testId.privKey, (err, id) => { + expect(err).to.not.exist + const out = id.toPrint() - expect(out.id).to.equal(testIdB58String) - expect(out.privKey).to.equal(testId.privKey) - expect(out.pubKey).to.equal(testId.pubKey) + expect(out.id).to.equal(testIdB58String) + expect(out.privKey).to.equal(testId.privKey) + expect(out.pubKey).to.equal(testId.pubKey) + done() + }) }) it('toBytes', () => { @@ -79,53 +106,80 @@ describe('PeerId', () => { }) describe('toJSON', () => { - it('full node', () => { - const id = PeerId.create({bits: 64}) - expect( - id.toB58String() - ).to.equal( - PeerId.createFromJSON(id.toJSON()).toB58String() - ) - expect( - id.privKey.bytes - ).to.deep.equal( - PeerId.createFromJSON(id.toJSON()).privKey.bytes - ) - expect( - id.pubKey.bytes - ).to.deep.equal( - PeerId.createFromJSON(id.toJSON()).pubKey.bytes - ) + it('full node', (done) => { + PeerId.create({bits: 512}, (err, id) => { + expect(err).to.not.exist + + PeerId.createFromJSON(id.toJSON(), (err, other) => { + expect(err).to.not.exist + expect( + id.toB58String() + ).to.equal( + other.toB58String() + ) + expect( + id.privKey.bytes + ).to.deep.equal( + other.privKey.bytes + ) + expect( + id.pubKey.bytes + ).to.deep.equal( + other.pubKey.bytes + ) + done() + }) + }) }) - it('only id', () => { - const key = crypto.generateKeyPair('RSA', 64) - const id = PeerId.createFromBytes(key.public.hash()) - expect( - id.toB58String() - ).to.equal( - PeerId.createFromJSON(id.toJSON()).toB58String() - ) - - expect(id.privKey).to.not.exist - expect(id.pubKey).to.not.exist + it('only id', (done) => { + crypto.generateKeyPair('RSA', 512, (err, key) => { + expect(err).to.not.exist + const id = PeerId.createFromBytes(key.public.hash()) + expect(id.privKey).to.not.exist + expect(id.pubKey).to.not.exist + + PeerId.createFromJSON(id.toJSON(), (err, other) => { + expect(err).to.not.exist + expect( + id.toB58String() + ).to.equal( + other.toB58String() + ) + done() + }) + }) }) it('go interop', () => { - const id = PeerId.createFromJSON(goId) - - expect( - mh.toB58String(id.privKey.public.hash()) - ).to.be.eql( - goId.id - ) + PeerId.createFromJSON(goId, (err, id) => { + expect(err).to.not.exist + expect( + mh.toB58String(id.privKey.public.hash()) + ).to.be.eql( + goId.id + ) + }) }) }) describe('throws on inconsistent data', () => { - const k1 = crypto.generateKeyPair('RSA', 64) - const k2 = crypto.generateKeyPair('RSA', 64) - const k3 = crypto.generateKeyPair('RSA', 64) + let k1, k2, k3 + before((done) => { + crypto.generateKeyPair('RSA', 512, (err, _k1) => { + if (err) return done(err) + k1 = _k1 + crypto.generateKeyPair('RSA', 512, (err, _k2) => { + if (err) return done(err) + k2 = _k2 + crypto.generateKeyPair('RSA', 512, (err, _k3) => { + if (err) return done(err) + k3 = _k3 + done() + }) + }) + }) + }) it('missmatch id - private key', () => { expect( From 4136f30f13651083dee29a8ca2379c10707ed5fb Mon Sep 17 00:00:00 2001 From: Friedel Ziegelmayer Date: Thu, 15 Sep 2016 11:05:32 +0200 Subject: [PATCH 02/11] revert async for methods that do not need it --- README.md | 17 ++----- package.json | 4 +- src/bin.js | 8 +++- src/index.js | 12 ++--- test/index.spec.js | 116 +++++++++++++++++++-------------------------- 5 files changed, 69 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index e5f121b..58bac9f 100644 --- a/README.md +++ b/README.md @@ -115,30 +115,23 @@ Creates a Peer ID from a buffer representing the key's multihash. ### `createFromB58String(str)` Creates a Peer ID from a Base58 string representing the key's multihash. -### `createFromPubKey(pubKey, cb)` +### `createFromPubKey(pubKey)` - `publicKey: Buffer` -- `cb: Function` -Creates a Peer ID from a buffer containing a public key and -calls back `cb` with `err, id`. +Creates a Peer ID from a buffer containing a public key. -### `createFromPrivKey(privKey, cb)` +### `createFromPrivKey(privKey)` - `privKey: Buffer` -- `cb: Function` -Creates a Peer ID from a buffer containing a private key and -calls back `cb` with `err, id`. +Creates a Peer ID from a buffer containing a private key. -### `createFromJSON(obj, cb)` +### `createFromJSON(obj)` - `obj.id: String` - The multihash encoded in `base58` - `obj.pubKey: String` - The public key in protobuf format, encoded in 'base64' - `obj.privKey: String` - The private key in protobuf format, encoded in 'base 64' -- `cb: Function` - -Calls back `cb` with `err, id`. ## Export diff --git a/package.json b/package.json index 0c266bb..a9a4afe 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "peer-id", "version": "0.7.0", "description": "IPFS Peer Id implementation in Node.js", - "main": "lib/index.js", + "main": "src/index.js", "bin": "src/bin.js", "jsnext:main": "src/index.js", "scripts": { @@ -53,4 +53,4 @@ "dignifiedquire ", "nginnever " ] -} \ No newline at end of file +} diff --git a/src/bin.js b/src/bin.js index b17b525..9388e68 100755 --- a/src/bin.js +++ b/src/bin.js @@ -4,4 +4,10 @@ const PeerId = require('./index.js') -console.log(JSON.stringify(PeerId.create().toJSON(), null, ' ')) +PeerId.create((err, id) => { + if (err) { + throw err + } + + console.log(JSON.stringify(id.toJSON(), null, 2)) +}) diff --git a/src/index.js b/src/index.js index bfd300b..b4fa907 100644 --- a/src/index.js +++ b/src/index.js @@ -118,28 +118,28 @@ exports.createFromB58String = function (str) { } // Public Key input will be a buffer -exports.createFromPubKey = function (key, cb) { +exports.createFromPubKey = function (key) { let buf = key if (typeof buf === 'string') { buf = new Buffer(key, 'base64') } const pubKey = crypto.unmarshalPublicKey(buf) - cb(null, new PeerId(pubKey.hash(), null, pubKey)) + return new PeerId(pubKey.hash(), null, pubKey) } // Private key input will be a string -exports.createFromPrivKey = function (key, cb) { +exports.createFromPrivKey = function (key) { let buf = key if (typeof buf === 'string') { buf = new Buffer(key, 'base64') } const privKey = crypto.unmarshalPrivateKey(buf) - cb(null, new PeerId(privKey.public.hash(), privKey)) + return new PeerId(privKey.public.hash(), privKey) } -exports.createFromJSON = function (obj, cb) { +exports.createFromJSON = function (obj) { let priv let pub @@ -151,7 +151,7 @@ exports.createFromJSON = function (obj, cb) { pub = crypto.unmarshalPublicKey(new Buffer(obj.pubKey, 'base64')) } - cb(null, new PeerId(mh.fromB58String(obj.id), priv, pub)) + return new PeerId(mh.fromB58String(obj.id), priv, pub) } function toB64Opt (val) { diff --git a/test/index.spec.js b/test/index.spec.js index ba41d36..c0940b4 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -43,37 +43,27 @@ describe('PeerId', () => { expect(testIdB58String).to.equal(id.toB58String()) }) - it('Recreate from a Public Key', (done) => { - PeerId.createFromPubKey(testId.pubKey, (err, id) => { - expect(err).to.not.exist - expect(testIdB58String).to.equal(id.toB58String()) - done() - }) + it('Recreate from a Public Key', () => { + const id = PeerId.createFromPubKey(testId.pubKey) + expect(testIdB58String).to.equal(id.toB58String()) }) - it('Recreate from a Private Key', (done) => { - PeerId.createFromPrivKey(testId.privKey, (err, id) => { - expect(err).to.not.exist - expect(testIdB58String).to.equal(id.toB58String()) + it('Recreate from a Private Key', () => { + const id = PeerId.createFromPrivKey(testId.privKey) + expect(testIdB58String).to.equal(id.toB58String()) - const encoded = new Buffer(testId.privKey, 'base64') - PeerId.createFromPrivKey(encoded, (err, id2) => { - expect(err).to.not.exist - expect(testIdB58String).to.equal(id2.toB58String()) - done() - }) - }) + const encoded = new Buffer(testId.privKey, 'base64') + const id2 = PeerId.createFromPrivKey(encoded) + expect(testIdB58String).to.equal(id2.toB58String()) }) it('Compare generated ID with one created from PubKey', (done) => { PeerId.create((err, id1) => { expect(err).to.not.exist - PeerId.createFromPubKey(id1.marshalPubKey(), (err, id2) => { - expect(err).to.not.exist - expect(id1.id).to.be.eql(id2.id) - done() - }) + const id2 = PeerId.createFromPubKey(id1.marshalPubKey()) + expect(id1.id).to.be.eql(id2.id) + done() }) }) @@ -88,16 +78,13 @@ describe('PeerId', () => { }) }) - it('Pretty printing', (done) => { - PeerId.createFromPrivKey(testId.privKey, (err, id) => { - expect(err).to.not.exist - const out = id.toPrint() + it('Pretty printing', () => { + const id = PeerId.createFromPrivKey(testId.privKey) + const out = id.toPrint() - expect(out.id).to.equal(testIdB58String) - expect(out.privKey).to.equal(testId.privKey) - expect(out.pubKey).to.equal(testId.pubKey) - done() - }) + expect(out.id).to.equal(testIdB58String) + expect(out.privKey).to.equal(testId.privKey) + expect(out.pubKey).to.equal(testId.pubKey) }) it('toBytes', () => { @@ -110,25 +97,24 @@ describe('PeerId', () => { PeerId.create({bits: 512}, (err, id) => { expect(err).to.not.exist - PeerId.createFromJSON(id.toJSON(), (err, other) => { - expect(err).to.not.exist - expect( - id.toB58String() - ).to.equal( - other.toB58String() - ) - expect( - id.privKey.bytes - ).to.deep.equal( - other.privKey.bytes - ) - expect( - id.pubKey.bytes - ).to.deep.equal( - other.pubKey.bytes - ) - done() - }) + const other = PeerId.createFromJSON(id.toJSON()) + + expect( + id.toB58String() + ).to.equal( + other.toB58String() + ) + expect( + id.privKey.bytes + ).to.deep.equal( + other.privKey.bytes + ) + expect( + id.pubKey.bytes + ).to.deep.equal( + other.pubKey.bytes + ) + done() }) }) @@ -139,27 +125,23 @@ describe('PeerId', () => { expect(id.privKey).to.not.exist expect(id.pubKey).to.not.exist - PeerId.createFromJSON(id.toJSON(), (err, other) => { - expect(err).to.not.exist - expect( - id.toB58String() - ).to.equal( - other.toB58String() - ) - done() - }) + const other = PeerId.createFromJSON(id.toJSON()) + expect( + id.toB58String() + ).to.equal( + other.toB58String() + ) + done() }) }) it('go interop', () => { - PeerId.createFromJSON(goId, (err, id) => { - expect(err).to.not.exist - expect( - mh.toB58String(id.privKey.public.hash()) - ).to.be.eql( - goId.id - ) - }) + const id = PeerId.createFromJSON(goId) + expect( + mh.toB58String(id.privKey.public.hash()) + ).to.be.eql( + goId.id + ) }) }) From 02aca7123a54069dff48b7f53b9a7d9b522d09c9 Mon Sep 17 00:00:00 2001 From: Friedel Ziegelmayer Date: Mon, 26 Sep 2016 14:20:15 +0200 Subject: [PATCH 03/11] update for the latest libp2p-crypto updates --- package.json | 13 +-- src/index.js | 114 +++++++++++++++++------ test/index.spec.js | 223 ++++++++++++++++++++++++--------------------- 3 files changed, 213 insertions(+), 137 deletions(-) diff --git a/package.json b/package.json index a9a4afe..e182f4d 100644 --- a/package.json +++ b/package.json @@ -2,18 +2,18 @@ "name": "peer-id", "version": "0.7.0", "description": "IPFS Peer Id implementation in Node.js", - "main": "src/index.js", + "main": "lib/index.js", "bin": "src/bin.js", "jsnext:main": "src/index.js", "scripts": { "lint": "aegir-lint", "build": "aegir-build", - "test": "aegir-test", + "test": "PHANTOM=off aegir-test", "test:node": "aegir-test node", - "test:browser": "aegir-test browser", - "release": "aegir-release", - "release-minor": "aegir-release --type minor", - "release-major": "aegir-release --type major", + "test:browser": "PHANTOM=off aegir-test browser", + "release": "PHANTOM=off aegir-release", + "release-minor": "PHANTOM=off aegir-release --type minor", + "release-major": "PHANTOM=off aegir-release --type major", "coverage": "aegir-coverage", "coverage-publish": "aegir-coverage publish" }, @@ -39,6 +39,7 @@ "pre-commit": "^1.1.3" }, "dependencies": { + "async": "^2.0.1", "libp2p-crypto": "^0.6.1", "multihashes": "^0.2.2" }, diff --git a/src/index.js b/src/index.js index b4fa907..f8364e5 100644 --- a/src/index.js +++ b/src/index.js @@ -7,28 +7,25 @@ const mh = require('multihashes') const crypto = require('libp2p-crypto') const assert = require('assert') +const waterfall = require('async/waterfall') class PeerId { constructor (id, privKey, pubKey) { assert(Buffer.isBuffer(id), 'invalid id provided') - if (pubKey) { - assert(id.equals(pubKey.hash()), 'inconsistent arguments') - } - - if (privKey) { - assert(id.equals(privKey.public.hash()), 'inconsistent arguments') - } - if (privKey && pubKey) { assert(privKey.public.bytes.equals(pubKey.bytes), 'inconsistent arguments') } this.id = id - this.privKey = privKey + this._privKey = privKey this._pubKey = pubKey } + get privKey () { + return this._privKey + } + get pubKey () { if (this._pubKey) { return this._pubKey @@ -88,20 +85,25 @@ exports = module.exports = PeerId exports.Buffer = Buffer // generation -exports.create = function (opts, cb) { +exports.create = function (opts, callback) { if (typeof opts === 'function') { - cb = opts + callback = opts opts = {} } opts = opts || {} opts.bits = opts.bits || 2048 - crypto.generateKeyPair('RSA', opts.bits, (err, privKey) => { + waterfall([ + (cb) => crypto.generateKeyPair('RSA', opts.bits, cb), + (privKey, cb) => privKey.public.hash((err, digest) => { + cb(err, digest, privKey) + }) + ], (err, digest, privKey) => { if (err) { - return cb(err) + return callback(err) } - cb(null, new PeerId(privKey.public.hash(), privKey)) + callback(null, new PeerId(digest, privKey)) }) } @@ -118,40 +120,94 @@ exports.createFromB58String = function (str) { } // Public Key input will be a buffer -exports.createFromPubKey = function (key) { +exports.createFromPubKey = function (key, callback) { let buf = key if (typeof buf === 'string') { buf = new Buffer(key, 'base64') } + if (typeof callback !== 'function') { + throw new Error('callback is required') + } + const pubKey = crypto.unmarshalPublicKey(buf) - return new PeerId(pubKey.hash(), null, pubKey) + pubKey.hash((err, digest) => { + if (err) { + return callback(err) + } + + callback(null, new PeerId(digest, null, pubKey)) + }) } // Private key input will be a string -exports.createFromPrivKey = function (key) { +exports.createFromPrivKey = function (key, callback) { let buf = key if (typeof buf === 'string') { buf = new Buffer(key, 'base64') } - const privKey = crypto.unmarshalPrivateKey(buf) - return new PeerId(privKey.public.hash(), privKey) -} + if (typeof callback !== 'function') { + throw new Error('callback is required') + } + + waterfall([ + (cb) => crypto.unmarshalPrivateKey(buf, cb), + (privKey, cb) => privKey.public.hash((err, digest) => { + cb(err, digest, privKey) + }) + ], (err, digest, privKey) => { + if (err) { + return callback(err) + } -exports.createFromJSON = function (obj) { - let priv - let pub + callback(null, new PeerId(digest, privKey)) + }) +} - if (obj.privKey) { - priv = crypto.unmarshalPrivateKey(new Buffer(obj.privKey, 'base64')) +exports.createFromJSON = function (obj, callback) { + if (typeof callback !== 'function') { + throw new Error('callback is required') } - if (obj.pubKey) { - pub = crypto.unmarshalPublicKey(new Buffer(obj.pubKey, 'base64')) + const id = mh.fromB58String(obj.id) + const rawPrivKey = obj.privKey && new Buffer(obj.privKey, 'base64') + const rawPubKey = obj.pubKey && new Buffer(obj.pubKey, 'base64') + const pub = rawPubKey && crypto.unmarshalPublicKey(rawPubKey) + + if (rawPrivKey) { + waterfall([ + (cb) => crypto.unmarshalPrivateKey(rawPrivKey, cb), + (priv, cb) => priv.public.hash((err, digest) => { + cb(err, digest, priv) + }), + (privDigest, priv, cb) => { + if (pub) { + pub.hash((err, pubDigest) => { + cb(err, privDigest, priv, pubDigest) + }) + } else { + cb(null, privDigest, priv) + } + } + ], (err, privDigest, priv, pubDigest) => { + if (err) { + return callback(err) + } + + if (pub && !privDigest.equals(pubDigest)) { + callback(new Error('Public and private key do not match')) + } + + if (id && !privDigest.equals(id)) { + callback(new Error('Id and private key do not match')) + } + + callback(null, new PeerId(id, priv, pub)) + }) + } else { + callback(null, new PeerId(id, null, pub)) } - - return new PeerId(mh.fromB58String(obj.id), priv, pub) } function toB64Opt (val) { diff --git a/test/index.spec.js b/test/index.spec.js index c0940b4..f6100e0 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -1,10 +1,11 @@ /* eslint max-nested-callbacks: ["error", 8] */ /* eslint-env mocha */ 'use strict' - +require('loud-rejection')() const expect = require('chai').expect const crypto = require('libp2p-crypto') const mh = require('multihashes') +const parallel = require('async/parallel') const PeerId = require('../src') @@ -43,34 +44,44 @@ describe('PeerId', () => { expect(testIdB58String).to.equal(id.toB58String()) }) - it('Recreate from a Public Key', () => { - const id = PeerId.createFromPubKey(testId.pubKey) - expect(testIdB58String).to.equal(id.toB58String()) + it('Recreate from a Public Key', (done) => { + PeerId.createFromPubKey(testId.pubKey, (err, id) => { + expect(err).to.not.exist + expect(testIdB58String).to.equal(id.toB58String()) + done() + }) }) - it('Recreate from a Private Key', () => { - const id = PeerId.createFromPrivKey(testId.privKey) - expect(testIdB58String).to.equal(id.toB58String()) + it('Recreate from a Private Key', (done) => { + PeerId.createFromPrivKey(testId.privKey, (err, id) => { + expect(err).to.not.exist + expect(testIdB58String).to.equal(id.toB58String()) - const encoded = new Buffer(testId.privKey, 'base64') - const id2 = PeerId.createFromPrivKey(encoded) - expect(testIdB58String).to.equal(id2.toB58String()) + const encoded = new Buffer(testId.privKey, 'base64') + PeerId.createFromPrivKey(encoded, (err, id2) => { + expect(err).to.not.exist + expect(testIdB58String).to.equal(id2.toB58String()) + done() + }) + }) }) it('Compare generated ID with one created from PubKey', (done) => { PeerId.create((err, id1) => { expect(err).to.not.exist - const id2 = PeerId.createFromPubKey(id1.marshalPubKey()) - expect(id1.id).to.be.eql(id2.id) - done() + PeerId.createFromPubKey(id1.marshalPubKey(), (err, id2) => { + expect(err).to.not.exist + expect(id1.id).to.be.eql(id2.id) + done() + }) }) }) it('Non-default # of bits', (done) => { - PeerId.create({ bits: 512 }, (err, shortId) => { + PeerId.create({ bits: 1024 }, (err, shortId) => { expect(err).to.not.exist - PeerId.create({ bits: 1024 }, (err, longId) => { + PeerId.create({ bits: 4096 }, (err, longId) => { expect(err).to.not.exist expect(shortId.privKey.bytes.length).is.below(longId.privKey.bytes.length) done() @@ -78,13 +89,15 @@ describe('PeerId', () => { }) }) - it('Pretty printing', () => { - const id = PeerId.createFromPrivKey(testId.privKey) - const out = id.toPrint() - - expect(out.id).to.equal(testIdB58String) - expect(out.privKey).to.equal(testId.privKey) - expect(out.pubKey).to.equal(testId.pubKey) + it('Pretty printing', (done) => { + PeerId.create((err, id1) => { + expect(err).to.not.exist + PeerId.createFromPrivKey(id1.toPrint().privKey, (err, id2) => { + expect(err).to.not.exist + expect(id1.toPrint()).to.be.eql(id2.toPrint()) + done() + }) + }) }) it('toBytes', () => { @@ -92,112 +105,118 @@ describe('PeerId', () => { expect(id.toBytes().toString('hex')).to.equal(testIdBytes.toString('hex')) }) - describe('toJSON', () => { + describe('fromJSON', () => { it('full node', (done) => { - PeerId.create({bits: 512}, (err, id) => { + PeerId.create({bits: 1024}, (err, id) => { expect(err).to.not.exist - const other = PeerId.createFromJSON(id.toJSON()) - - expect( - id.toB58String() - ).to.equal( - other.toB58String() - ) - expect( - id.privKey.bytes - ).to.deep.equal( - other.privKey.bytes - ) - expect( - id.pubKey.bytes - ).to.deep.equal( - other.pubKey.bytes - ) - done() + PeerId.createFromJSON(id.toJSON(), (err, other) => { + expect(err).to.not.exist + expect( + id.toB58String() + ).to.equal( + other.toB58String() + ) + expect( + id.privKey.bytes + ).to.deep.equal( + other.privKey.bytes + ) + expect( + id.pubKey.bytes + ).to.deep.equal( + other.pubKey.bytes + ) + done() + }) }) }) it('only id', (done) => { - crypto.generateKeyPair('RSA', 512, (err, key) => { + crypto.generateKeyPair('RSA', 1024, (err, key) => { expect(err).to.not.exist - const id = PeerId.createFromBytes(key.public.hash()) - expect(id.privKey).to.not.exist - expect(id.pubKey).to.not.exist - - const other = PeerId.createFromJSON(id.toJSON()) - expect( - id.toB58String() - ).to.equal( - other.toB58String() - ) - done() + key.public.hash((err, digest) => { + expect(err).to.not.exist + + const id = PeerId.createFromBytes(digest) + expect(id.privKey).to.not.exist + expect(id.pubKey).to.not.exist + + PeerId.createFromJSON(id.toJSON(), (err, other) => { + expect(err).to.not.exist + expect( + id.toB58String() + ).to.equal( + other.toB58String() + ) + done() + }) + }) }) }) - it('go interop', () => { - const id = PeerId.createFromJSON(goId) - expect( - mh.toB58String(id.privKey.public.hash()) - ).to.be.eql( - goId.id - ) + it('go interop', (done) => { + PeerId.createFromJSON(goId, (err, id) => { + expect(err).to.not.exist + id.privKey.public.hash((err, digest) => { + expect(err).to.not.exist + expect( + mh.toB58String(digest) + ).to.be.eql( + goId.id + ) + done() + }) + }) }) }) describe('throws on inconsistent data', () => { let k1, k2, k3 before((done) => { - crypto.generateKeyPair('RSA', 512, (err, _k1) => { - if (err) return done(err) - k1 = _k1 - crypto.generateKeyPair('RSA', 512, (err, _k2) => { - if (err) return done(err) - k2 = _k2 - crypto.generateKeyPair('RSA', 512, (err, _k3) => { - if (err) return done(err) - k3 = _k3 - done() - }) - }) + parallel([ + (cb) => crypto.generateKeyPair('RSA', 1024, cb), + (cb) => crypto.generateKeyPair('RSA', 1024, cb), + (cb) => crypto.generateKeyPair('RSA', 1024, cb) + ], (err, keys) => { + if (err) { + return done(err) + } + + k1 = keys[0] + k2 = keys[1] + k3 = keys[2] + done() }) }) - it('missmatch id - private key', () => { - expect( - () => new PeerId(k1.public.hash(), k2) - ).to.throw( - /inconsistent arguments/ - ) - }) - - it('missmatch id - public key', () => { - expect( - () => new PeerId(k1.public.hash(), null, k2.public) - ).to.throw( - /inconsistent arguments/ - ) - }) - - it('missmatch private - public key', () => { - expect( - () => new PeerId(k1.public.hash(), k1, k2.public) - ).to.throw( - /inconsistent arguments/ - ) + it('missmatch private - public key', (done) => { + k1.public.hash((err, digest) => { + expect(err).to.not.exist + expect( + () => new PeerId(digest, k1, k2.public) + ).to.throw( + /inconsistent arguments/ + ) + done() + }) }) - it('missmatch id - private - public key', () => { - expect( - () => new PeerId(k1.public.hash(), k1, k3.public) - ).to.throw( - /inconsistent arguments/ - ) + it('missmatch id - private - public key', (done) => { + k1.public.hash((err, digest) => { + expect(err).to.not.exist + expect( + () => new PeerId(digest, k1, k3.public) + ).to.throw( + /inconsistent arguments/ + ) + done() + }) }) it('invalid id', () => { expect( - () => new PeerId(k1.public.hash().toString()) + () => new PeerId('hello world') ).to.throw( /invalid id/ ) From 1615516cdc1d4ccdc7283220e7265d139ac6caff Mon Sep 17 00:00:00 2001 From: Friedel Ziegelmayer Date: Wed, 28 Sep 2016 23:02:41 +0200 Subject: [PATCH 04/11] chore: remove unused .aegir config --- .aegir.js | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 .aegir.js diff --git a/.aegir.js b/.aegir.js deleted file mode 100644 index e3151ab..0000000 --- a/.aegir.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict' - -const path = require('path') - -module.exports = { - webpack: { - resolve: { - alias: { - 'node-forge': path.resolve( - path.dirname(require.resolve('libp2p-crypto')), - '../vendor/forge.bundle.js' - ) - } - } - } -} From 55bd0206d3254950fe140031d315d33152a5e2af Mon Sep 17 00:00:00 2001 From: Friedel Ziegelmayer Date: Thu, 6 Oct 2016 13:51:41 +0200 Subject: [PATCH 05/11] cr round1 --- README.md | 33 ++++++++++++++++++++++++++++++--- package.json | 2 +- test/index.spec.js | 2 +- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 58bac9f..0e27441 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,33 @@ > [IPFS](https://github.com/ipfs/ipfs) Peer ID implementation in JavaScript. +- [Description](#description) +- [Example](#example) +- [Installation](#installation) + - [npm](#npm) +- [Setup](#setup) + - [Node.js](#nodejs) + - [Browser: Browserify, Webpack, other bundlers](#browser-browserify-webpack-other-bundlers) + - [Browser: `