Skip to content

Commit

Permalink
feat(peerid): support creating from secp256k1; harmonize algo with Go
Browse files Browse the repository at this point in the history
  • Loading branch information
aknuds1 committed Jul 11, 2019
1 parent bbabd74 commit 6080f4a
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 58 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@
"dirty-chai": "^2.0.1"
},
"dependencies": {
"async": "^2.6.2",
"class-is": "^1.1.0",
"libp2p-crypto": "~0.16.1",
"multihashes": "~0.4.14"
"async": "^3.0.1",
"class-is": "^1.1.0",
"multihashes": "~0.4.15"
},
"repository": {
"type": "git",
Expand Down
119 changes: 64 additions & 55 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,27 @@ const PeerIdWithIs = withIs(PeerId, { className: 'PeerId', symbolName: '@libp2p/

exports = module.exports = PeerIdWithIs

const computeDigest = (pubKey, cb) => {
if (pubKey.bytes.length <= 42) {
const digest = mh.encode(pubKey.bytes, 'identity')
cb(null, digest)
} else {
pubKey.hash((err, digest) => {
cb(err, digest)
})
}
}

const computePeerId = (privKey, pubKey, cb) => {
computeDigest(pubKey, (err, digest) => {
if (err != null) {
cb(err)
} else {
cb(null, new PeerIdWithIs(digest, privKey, pubKey))
}
})
}

// generation
exports.create = function (opts, callback) {
if (typeof opts === 'function') {
Expand All @@ -145,18 +166,14 @@ exports.create = function (opts, callback) {
}
opts = opts || {}
opts.bits = opts.bits || 2048
opts.keyType = opts.keyType || 'RSA'

waterfall([
(cb) => cryptoKeys.generateKeyPair('RSA', opts.bits, cb),
(privKey, cb) => privKey.public.hash((err, digest) => {
cb(err, digest, privKey)
})
], (err, digest, privKey) => {
if (err) {
return callback(err)
cryptoKeys.generateKeyPair(opts.keyType, opts.bits, (err, privKey) => {
if (err != null) {
callback(err)
} else {
computePeerId(privKey, privKey.public, callback)
}

callback(null, new PeerIdWithIs(digest, privKey))
})
}

Expand Down Expand Up @@ -193,13 +210,7 @@ exports.createFromPubKey = function (key, callback) {
return callback(err)
}

pubKey.hash((err, digest) => {
if (err) {
return callback(err)
}

callback(null, new PeerIdWithIs(digest, null, pubKey))
})
computePeerId(null, pubKey, callback)
}

// Private key input will be a string
Expand All @@ -220,17 +231,12 @@ exports.createFromPrivKey = function (key, callback) {
return callback(err)
}

waterfall([
(cb) => cryptoKeys.unmarshalPrivateKey(buf, cb),
(privKey, cb) => privKey.public.hash((err, digest) => {
cb(err, digest, privKey)
})
], (err, digest, privKey) => {
if (err) {
return callback(err)
cryptoKeys.unmarshalPrivateKey(buf, (err, privKey) => {
if (err != null) {
callback(err)
} else {
computePeerId(privKey, privKey.public, callback)
}

callback(null, new PeerIdWithIs(digest, privKey, privKey.public))
})
}

Expand All @@ -253,39 +259,42 @@ exports.createFromJSON = function (obj, callback) {
return callback(err)
}

if (rawPrivKey) {
waterfall([
(cb) => cryptoKeys.unmarshalPrivateKey(rawPrivKey, cb),
(priv, cb) => priv.public.hash((err, digest) => {
if (!rawPrivKey) {
callback(null, new PeerIdWithIs(id, null, pub))
return
}

waterfall([
(cb) => cryptoKeys.unmarshalPrivateKey(rawPrivKey, cb),
(priv, cb) => {
computeDigest(priv.public, (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)
})
},
(privDigest, priv, cb) => {
if (pub) {
computeDigest(pub, (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)) {
return callback(new Error('Public and private key do not match'))
}
if (pub && !privDigest.equals(pubDigest)) {
return callback(new Error('Public and private key do not match'))
}

if (id && !privDigest.equals(id)) {
return callback(new Error('Id and private key do not match'))
}
if (id && !privDigest.equals(id)) {
return callback(new Error('Id and private key do not match'))
}

callback(null, new PeerIdWithIs(id, priv, pub))
})
} else {
callback(null, new PeerIdWithIs(id, null, pub))
}
callback(null, new PeerIdWithIs(id, priv, pub))
})
}

exports.isPeerId = function (peerId) {
Expand Down
42 changes: 42 additions & 0 deletions test/peer-id.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const expect = chai.expect
const crypto = require('libp2p-crypto')
const mh = require('multihashes')
const parallel = require('async/parallel')
const waterfall = require('async/waterfall')

const PeerId = require('../src')

Expand Down Expand Up @@ -40,6 +41,15 @@ describe('PeerId', () => {
})
})

it('can be created for a Secp256k1 key', (done) => {
PeerId.create({keyType: 'secp256k1', bits: 256,}, (err, id) => {
const expB58 = mh.toB58String(mh.encode(id.pubKey.bytes, 'identity'))
expect(err).to.not.exist()
expect(id.toB58String()).to.equal(expB58)
done()
})
})

it('isPeerId', (done) => {
PeerId.create(testOpts, (err, id) => {
expect(err).to.not.exist()
Expand Down Expand Up @@ -85,6 +95,22 @@ describe('PeerId', () => {
})
})

it('can be created from a Secp256k1 public key', (done) => {
waterfall([
(cb) => {
crypto.keys.generateKeyPair('secp256k1', 256, cb)
},
(privKey, cb) => {
PeerId.createFromPubKey(privKey.public.bytes, cb)
},
], (err, id) => {
expect(err).to.not.exist()
const expB58 = mh.toB58String(mh.encode(id.pubKey.bytes, 'identity'))
expect(id.toB58String()).to.equal(expB58)
done()
})
})

it('Recreate from a Private Key', (done) => {
PeerId.createFromPrivKey(testId.privKey, (err, id) => {
expect(err).to.not.exist()
Expand All @@ -100,6 +126,22 @@ describe('PeerId', () => {
})
})

it('can be created from a Secp256k1 private key', (done) => {
waterfall([
(cb) => {
crypto.keys.generateKeyPair('secp256k1', 256, cb)
},
(privKey, cb) => {
PeerId.createFromPrivKey(privKey.bytes, cb)
},
], (err, id) => {
expect(err).to.not.exist()
const expB58 = mh.toB58String(mh.encode(id.pubKey.bytes, 'identity'))
expect(id.toB58String()).to.equal(expB58)
done()
})
})

it('Compare generated ID with one created from PubKey', (done) => {
PeerId.create(testOpts, (err, id1) => {
expect(err).to.not.exist()
Expand Down

0 comments on commit 6080f4a

Please sign in to comment.