From 17440a3f9a67092499f5cb5c828936a8d06ad990 Mon Sep 17 00:00:00 2001 From: Arve Knudsen Date: Thu, 11 Jul 2019 21:31:39 +0200 Subject: [PATCH] feat(peerid): support creating from secp256k1; harmonize algo with Go (#95) --- README.md | 4 ++-- package.json | 2 +- src/index.js | 32 +++++++++++++++++++++----------- test/peer-id.spec.js | 20 ++++++++++++++++++++ 4 files changed, 44 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index b158aa2..ad9c64a 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ The public key is a base64 encoded string of a protobuf containing an RSA DER bu ```JavaScript const PeerId = require('peer-id') -const id = await PeerId.create({ bits: 1024 }) +const id = await PeerId.create({ bits: 1024, keyType: 'rsa' }) console.log(JSON.stringify(id.toJSON(), null, 2)) ``` @@ -127,7 +127,7 @@ The key format is detailed in [libp2p-crypto](https://github.com/libp2p/js-libp2 Generates a new Peer ID, complete with public/private keypair. -- `opts: Object`: Default: `{bits: 2048}` +- `opts: Object`: Default: `{bits: 2048, keyType: 'rsa'}` Returns `Promise`. diff --git a/package.json b/package.json index 31d64bd..803528a 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "dependencies": { "class-is": "^1.1.0", "libp2p-crypto": "~0.17.0", - "multihashes": "~0.4.14" + "multihashes": "~0.4.15" }, "repository": { "type": "git", diff --git a/src/index.js b/src/index.js index 8ca1040..fc35d38 100644 --- a/src/index.js +++ b/src/index.js @@ -135,15 +135,27 @@ const PeerIdWithIs = withIs(PeerId, { exports = module.exports = PeerIdWithIs +const computeDigest = (pubKey) => { + if (pubKey.bytes.length <= 42) { + return mh.encode(pubKey.bytes, 'identity') + } else { + return pubKey.hash() + } +} + +const computePeerId = async (privKey, pubKey) => { + const digest = await computeDigest(pubKey) + return new PeerIdWithIs(digest, privKey, pubKey) +} + // generation exports.create = async (opts) => { opts = opts || {} opts.bits = opts.bits || 2048 + opts.keyType = opts.keyType || 'RSA' - const key = await cryptoKeys.generateKeyPair('RSA', opts.bits) - const digest = await key.public.hash() - - return new PeerIdWithIs(digest, key) + const key = await cryptoKeys.generateKeyPair(opts.keyType, opts.bits) + return computePeerId(key, key.public) } exports.createFromHexString = (str) => { @@ -171,8 +183,7 @@ exports.createFromPubKey = async (key) => { } const pubKey = await cryptoKeys.unmarshalPublicKey(buf) - const digest = await pubKey.hash() - return new PeerIdWithIs(digest, null, pubKey) + return computePeerId(null, pubKey) } // Private key input will be a string @@ -188,9 +199,7 @@ exports.createFromPrivKey = async (key) => { } const privKey = await cryptoKeys.unmarshalPrivateKey(buf) - const digest = await privKey.public.hash() - - return new PeerIdWithIs(digest, privKey, privKey.public) + return computePeerId(privKey, privKey.public) } exports.createFromJSON = async (obj) => { @@ -204,11 +213,12 @@ exports.createFromJSON = async (obj) => { } const privKey = await cryptoKeys.unmarshalPrivateKey(rawPrivKey) - const privDigest = await privKey.public.hash() + const privDigest = await computeDigest(privKey.public) + let pubDigest if (pub) { - pubDigest = await pub.hash() + pubDigest = await computeDigest(pub) } if (pub && !privDigest.equals(pubDigest)) { diff --git a/test/peer-id.spec.js b/test/peer-id.spec.js index 468273d..2e2c052 100644 --- a/test/peer-id.spec.js +++ b/test/peer-id.spec.js @@ -36,6 +36,12 @@ describe('PeerId', () => { expect(id.toB58String().length).to.equal(46) }) + it('can be created for a Secp256k1 key', async () => { + const id = await PeerId.create({ keyType: 'secp256k1', bits: 256 }) + const expB58 = mh.toB58String(mh.encode(id.pubKey.bytes, 'identity')) + expect(id.toB58String()).to.equal(expB58) + }) + it('isPeerId', async () => { const id = await PeerId.create(testOpts) expect(PeerId.isPeerId(id)).to.equal(true) @@ -80,6 +86,20 @@ describe('PeerId', () => { expect(id.marshalPubKey()).to.deep.equal(id2.marshalPubKey()) }) + it('can be created from a Secp256k1 public key', async () => { + const privKey = await crypto.keys.generateKeyPair('secp256k1', 256) + const id = await PeerId.createFromPubKey(privKey.public.bytes) + const expB58 = mh.toB58String(mh.encode(id.pubKey.bytes, 'identity')) + expect(id.toB58String()).to.equal(expB58) + }) + + it('can be created from a Secp256k1 private key', async () => { + const privKey = await crypto.keys.generateKeyPair('secp256k1', 256) + const id = await PeerId.createFromPrivKey(privKey.bytes) + const expB58 = mh.toB58String(mh.encode(id.pubKey.bytes, 'identity')) + expect(id.toB58String()).to.equal(expB58) + }) + it('Compare generated ID with one created from PubKey', async () => { const id1 = await PeerId.create(testOpts) const id2 = await PeerId.createFromPubKey(id1.marshalPubKey())