From 35f196ea4deffd9f0de53afff6bd8aba5e4db9f2 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Tue, 17 Mar 2020 10:59:23 +0000 Subject: [PATCH] fix: add buffer and update deps (#25) * fix: add buffer and update deps update secp256k1 dep and fix code use multibase to encode b58 avoid un-necessary circular dependency no libp2p-crypto use only sha256 from multihashing-async * Update src/crypto.js Co-Authored-By: Jacob Heun * chore: remove commitlint from CI Co-authored-by: Jacob Heun --- .gitignore | 1 + .travis.yml | 2 +- package.json | 16 +++++++--------- src/crypto.js | 38 ++++++++++++++++++++++++++----------- src/index.js | 11 +++++------ test/fixtures/go-interop.js | 2 +- test/secp256k1.spec.js | 16 ++++++++-------- 7 files changed, 50 insertions(+), 36 deletions(-) diff --git a/.gitignore b/.gitignore index 452c69d..f99b5ca 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ build node_modules dist +docs package-lock.json yarn.lock .vscode diff --git a/.travis.yml b/.travis.yml index 11e06a6..cb1d170 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ stages: node_js: - '10' + - '12' os: - linux @@ -23,7 +24,6 @@ jobs: include: - stage: check script: - - npx aegir commitlint --travis - npx aegir dep-check - npm run lint diff --git a/package.json b/package.json index e1499b9..9c90f28 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,6 @@ "description": "Support for secp256k1 keys in libp2p-crypto", "leadMaintainer": "Friedel Ziegelmayer ", "main": "src/index.js", - "browser": { - "secp256k1": "secp256k1/js" - }, "scripts": { "lint": "aegir lint", "build": "aegir build", @@ -27,18 +24,19 @@ ], "license": "MIT", "dependencies": { - "bs58": "^4.0.1", - "multihashing-async": "^0.8.0", - "nodeify": "^1.0.1", - "safe-buffer": "^5.1.2", - "secp256k1": "^3.6.2" + "buffer": "^5.5.0", + "is-typedarray": "^1.0.0", + "multibase": "^0.6.0", + "multihashing-async": "^0.8.1", + "secp256k1": "^4.0.0" }, "devDependencies": { "aegir": "^21.0.2", "benchmark": "^2.1.4", "chai": "^4.2.0", "dirty-chai": "^2.0.1", - "libp2p-crypto": "~0.17.2" + "libp2p-crypto": "~0.17.2", + "protons": "^1.1.0" }, "engines": { "node": ">=6.0.0", diff --git a/src/crypto.js b/src/crypto.js index fbafb91..1db25c4 100644 --- a/src/crypto.js +++ b/src/crypto.js @@ -1,10 +1,26 @@ 'use strict' +const { Buffer } = require('buffer') +var isTypedArray = require('is-typedarray').strict const secp256k1 = require('secp256k1') -const multihashing = require('multihashing-async') - +const sha = require('multihashing-async/src/sha') const HASH_ALGORITHM = 'sha2-256' +function typedArrayTobuffer (arr) { + if (isTypedArray(arr)) { + // To avoid a copy, use the typed array's underlying ArrayBuffer to back new Buffer + var buf = Buffer.from(arr.buffer) + if (arr.byteLength !== arr.buffer.byteLength) { + // Respect the "view", i.e. byteOffset and byteLength, without doing a copy + buf = buf.slice(arr.byteOffset, arr.byteOffset + arr.byteLength) + } + return buf + } else { + // Pass through all other types to `Buffer.from` + return Buffer.from(arr) + } +} + module.exports = (randomBytes) => { const privateKeyLength = 32 @@ -17,26 +33,26 @@ module.exports = (randomBytes) => { } async function hashAndSign (key, msg) { - const digest = await multihashing.digest(msg, HASH_ALGORITHM) - const sig = secp256k1.sign(digest, key) - return secp256k1.signatureExport(sig.signature) + const digest = await sha.digest(msg, HASH_ALGORITHM) + const sig = secp256k1.ecdsaSign(digest, key) + return typedArrayTobuffer(secp256k1.signatureExport(sig.signature)) } async function hashAndVerify (key, sig, msg) { - const digest = await multihashing.digest(msg, HASH_ALGORITHM) - sig = secp256k1.signatureImport(sig) - return secp256k1.verify(digest, sig, key) + const digest = await sha.digest(msg, HASH_ALGORITHM) + sig = typedArrayTobuffer(secp256k1.signatureImport(sig)) + return secp256k1.ecdsaVerify(sig, digest, key) } function compressPublicKey (key) { if (!secp256k1.publicKeyVerify(key)) { throw new Error('Invalid public key') } - return secp256k1.publicKeyConvert(key, true) + return typedArrayTobuffer(secp256k1.publicKeyConvert(key, true)) } function decompressPublicKey (key) { - return secp256k1.publicKeyConvert(key, false) + return typedArrayTobuffer(secp256k1.publicKeyConvert(key, false)) } function validatePrivateKey (key) { @@ -53,7 +69,7 @@ module.exports = (randomBytes) => { function computePublicKey (privateKey) { validatePrivateKey(privateKey) - return secp256k1.publicKeyCreate(privateKey) + return typedArrayTobuffer(secp256k1.publicKeyCreate(privateKey)) } return { diff --git a/src/index.js b/src/index.js index a1299b2..13ebfe8 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ 'use strict' -const bs58 = require('bs58') -const multihashing = require('multihashing-async') +const multibase = require('multibase') +const sha = require('multihashing-async/src/sha') module.exports = (keysProtobuf, randomBytes, crypto) => { crypto = crypto || require('./crypto')(randomBytes) @@ -32,7 +32,7 @@ module.exports = (keysProtobuf, randomBytes, crypto) => { } hash () { - return multihashing(this.bytes, 'sha2-256') + return sha.multihashing(this.bytes, 'sha2-256') } } @@ -68,7 +68,7 @@ module.exports = (keysProtobuf, randomBytes, crypto) => { } hash () { - return multihashing(this.bytes, 'sha2-256') + return sha.multihashing(this.bytes, 'sha2-256') } /** @@ -83,8 +83,7 @@ module.exports = (keysProtobuf, randomBytes, crypto) => { */ async id () { const hash = await this.public.hash() - - return bs58.encode(hash) + return multibase.encode('base58btc', hash).toString().slice(1) } } diff --git a/test/fixtures/go-interop.js b/test/fixtures/go-interop.js index 8f18c1a..bebda0b 100644 --- a/test/fixtures/go-interop.js +++ b/test/fixtures/go-interop.js @@ -1,6 +1,6 @@ 'use strict' -const Buffer = require('safe-buffer').Buffer +const { Buffer } = require('buffer') // The keypair and signature below were generated in a gore repl session (https://github.com/motemen/gore) // using the secp256k1 fork of go-libp2p-crypto by github user @vyzo diff --git a/test/secp256k1.spec.js b/test/secp256k1.spec.js index c039216..0863ca4 100644 --- a/test/secp256k1.spec.js +++ b/test/secp256k1.spec.js @@ -1,14 +1,14 @@ /* eslint-env mocha */ 'use strict' +const { Buffer } = require('buffer') const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) - -const libp2pCrypto = require('libp2p-crypto') -const keysPBM = libp2pCrypto.keys.keysPBM -const randomBytes = libp2pCrypto.randomBytes +const protobuf = require('protons') +const keysPBM = protobuf(require('libp2p-crypto/src/keys/keys.proto')) +const randomBytes = require('libp2p-crypto/src/random-bytes') const crypto = require('../src/crypto')(randomBytes) describe('secp256k1 keys', () => { @@ -136,7 +136,7 @@ describe('handles generation of invalid key', () => { try { await secp256k1.generateKeyPair() } catch (err) { - return expect(err.message).to.equal('Invalid private key') + return expect(err.message).to.equal('Expected private key to be an Uint8Array with length 32') } throw new Error('Expected error to be thrown') }) @@ -182,7 +182,7 @@ describe('crypto functions', () => { try { await crypto.hashAndSign(Buffer.from('42'), Buffer.from('Hello')) } catch (err) { - return expect(err.message).to.equal('private key length is invalid') + return expect(err.message).to.equal('Expected private key to be an Uint8Array with length 32') } throw new Error('Expected error to be thrown') }) @@ -202,7 +202,7 @@ describe('crypto functions', () => { try { await crypto.hashAndVerify(pubKey, Buffer.from('invalid-sig'), Buffer.from('hello')) } catch (err) { - return expect(err.message).to.equal('couldn\'t parse DER signature') + return expect(err.message).to.equal('Signature could not be parsed') } throw new Error('Expected error to be thrown') }) @@ -211,7 +211,7 @@ describe('crypto functions', () => { try { await crypto.hashAndSign(Buffer.from('42'), Buffer.from('Hello')) } catch (err) { - return expect(err.message).to.equal('private key length is invalid') + return expect(err.message).to.equal('Expected private key to be an Uint8Array with length 32') } throw new Error('Expected error to be thrown') })