From c39c6ea58e1befa2bd238ffd0cfcd772c9c69e20 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Sun, 15 Mar 2020 23:18:34 +0000 Subject: [PATCH 1/5] fix: add buffer, cleanup, reduce size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - add buffer related to https://github.com/ipfs/js-ipfs/issues/2924 - remove unnecessary eslint ignore - remove tweelnacl and use node-forge - remove browserify-aes and use node-forge - use multibase to encode b58 - require only sha256 from multihashing - reduce bundle size after all the deps here https://github.com/ipfs/js-ipfs/issues/2924 are merged libp2p-crypto will be able to be bundle with `node: false` 🎉 --- .eslintignore | 1 - package.json | 13 +++----- src/aes/ciphers-browser.js | 27 +++++++++++++--- src/aes/index-browser.js | 34 --------------------- src/hmac/index-browser.js | 2 +- src/keys/ed25519-class.js | 19 ++++++------ src/keys/ed25519.js | 17 ++++++----- src/keys/index.js | 2 +- src/keys/key-stretcher.js | 2 +- src/keys/rsa-browser.js | 1 + src/keys/rsa-class.js | 12 ++++---- test/aes/aes.spec.js | 2 +- test/fixtures/go-elliptic-key.js | 1 + test/fixtures/go-key-ed25519.js | 1 + test/fixtures/go-key-rsa.js | 2 +- test/fixtures/go-stretch-key.js | 2 +- test/fixtures/secp256k1.js | 1 + test/helpers/test-garbage-error-handling.js | 1 + test/hmac/hmac.spec.js | 2 +- test/keys/ed25519.spec.js | 1 + test/keys/rsa.spec.js | 1 + test/util.spec.js | 1 + 22 files changed, 67 insertions(+), 78 deletions(-) delete mode 100644 .eslintignore delete mode 100644 src/aes/index-browser.js diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index fb5e189e..00000000 --- a/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -src/keys/keys.proto.js \ No newline at end of file diff --git a/package.json b/package.json index 098d2040..97d4f9e6 100644 --- a/package.json +++ b/package.json @@ -37,25 +37,20 @@ ], "license": "MIT", "dependencies": { - "asmcrypto.js": "^2.3.2", - "bn.js": "^5.0.0", - "browserify-aes": "^1.2.0", - "bs58": "^4.0.1", + "buffer": "^5.5.0", "err-code": "^2.0.0", "iso-random-stream": "^1.1.0", "keypair": "^1.0.1", "libp2p-crypto-secp256k1": "~0.4.0", - "multihashing-async": "~0.8.0", + "multibase": "^0.6.0", + "multihashing-async": "^0.8.1", "node-forge": "~0.9.1", "pem-jwk": "^2.0.0", "protons": "^1.0.1", - "rsa-pem-to-jwk": "^1.1.3", - "tweetnacl": "^1.0.1", "ursa-optional": "~0.10.1" }, "devDependencies": { - "@types/bn.js": "^4.11.6", - "@types/chai": "^4.2.7", + "@types/chai": "^4.2.11", "@types/chai-string": "^1.4.2", "@types/dirty-chai": "^2.0.2", "@types/mocha": "^7.0.1", diff --git a/src/aes/ciphers-browser.js b/src/aes/ciphers-browser.js index 5aee05ae..4e8f160c 100644 --- a/src/aes/ciphers-browser.js +++ b/src/aes/ciphers-browser.js @@ -1,8 +1,27 @@ 'use strict' - -const crypto = require('browserify-aes') +const { Buffer } = require('buffer') +require('node-forge/lib/aes') +const forge = require('node-forge/lib/forge') module.exports = { - createCipheriv: crypto.createCipheriv, - createDecipheriv: crypto.createDecipheriv + createCipheriv: (mode, key, iv) => { + const cipher2 = forge.cipher.createCipher('AES-CTR', key.toString('binary')) + cipher2.start({ iv: iv.toString('binary') }) + return { + update: (data) => { + cipher2.update(forge.util.createBuffer(data.toString('binary'))) + return Buffer.from(cipher2.output.getBytes(), 'binary') + } + } + }, + createDecipheriv: (mode, key, iv) => { + const cipher2 = forge.cipher.createDecipher('AES-CTR', key.toString('binary')) + cipher2.start({ iv: iv.toString('binary') }) + return { + update: (data) => { + cipher2.update(forge.util.createBuffer(data.toString('binary'))) + return Buffer.from(cipher2.output.getBytes(), 'binary') + } + } + } } diff --git a/src/aes/index-browser.js b/src/aes/index-browser.js deleted file mode 100644 index a806917e..00000000 --- a/src/aes/index-browser.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict' - -const asm = require('asmcrypto.js') -const validateCipherMode = require('./cipher-mode') - -exports.create = async function (key, iv) { // eslint-disable-line require-await - // Throws an error if mode is invalid - validateCipherMode(key) - - const enc = new asm.AES_CTR.Encrypt({ - key: key, - nonce: iv - }) - const dec = new asm.AES_CTR.Decrypt({ - key: key, - nonce: iv - }) - - const res = { - async encrypt (data) { // eslint-disable-line require-await - return Buffer.from( - enc.process(data).result - ) - }, - - async decrypt (data) { // eslint-disable-line require-await - return Buffer.from( - dec.process(data).result - ) - } - } - - return res -} diff --git a/src/hmac/index-browser.js b/src/hmac/index-browser.js index 1eeb7dfc..cda9da27 100644 --- a/src/hmac/index-browser.js +++ b/src/hmac/index-browser.js @@ -1,5 +1,5 @@ 'use strict' - +const { Buffer } = require('buffer') const webcrypto = require('../webcrypto') const lengths = require('./lengths') diff --git a/src/keys/ed25519-class.js b/src/keys/ed25519-class.js index b9f71069..1cba96f7 100644 --- a/src/keys/ed25519-class.js +++ b/src/keys/ed25519-class.js @@ -1,8 +1,9 @@ 'use strict' -const multihashing = require('multihashing-async') +const { Buffer } = require('buffer') +const sha = require('multihashing-async/src/sha') const protobuf = require('protons') -const bs58 = require('bs58') +const multibase = require('multibase') const errcode = require('err-code') const crypto = require('./ed25519') @@ -33,7 +34,7 @@ class Ed25519PublicKey { } async hash () { // eslint-disable-line require-await - return multihashing(this.bytes, 'sha2-256') + return sha.multihashing(this.bytes, 'sha2-256') } } @@ -69,7 +70,7 @@ class Ed25519PrivateKey { } async hash () { // eslint-disable-line require-await - return multihashing(this.bytes, 'sha2-256') + return sha.multihashing(this.bytes, 'sha2-256') } /** @@ -83,7 +84,7 @@ class Ed25519PrivateKey { */ async id () { const hash = await this.public.hash() - return bs58.encode(hash) + return multibase.encode('base58btc', hash).toString().slice(1) } } @@ -100,13 +101,13 @@ function unmarshalEd25519PublicKey (bytes) { } async function generateKeyPair () { - const { secretKey, publicKey } = await crypto.generateKey() - return new Ed25519PrivateKey(secretKey, publicKey) + const { privateKey, publicKey } = await crypto.generateKey() + return new Ed25519PrivateKey(privateKey, publicKey) } async function generateKeyPairFromSeed (seed) { - const { secretKey, publicKey } = await crypto.generateKeyFromSeed(seed) - return new Ed25519PrivateKey(secretKey, publicKey) + const { privateKey, publicKey } = await crypto.generateKeyFromSeed(seed) + return new Ed25519PrivateKey(privateKey, publicKey) } function ensureKey (key, length) { diff --git a/src/keys/ed25519.js b/src/keys/ed25519.js index cbe6c865..140cc14b 100644 --- a/src/keys/ed25519.js +++ b/src/keys/ed25519.js @@ -1,23 +1,24 @@ 'use strict' -const nacl = require('tweetnacl') - -exports.publicKeyLength = nacl.sign.publicKeyLength -exports.privateKeyLength = nacl.sign.secretKeyLength +require('node-forge/lib/ed25519') +const forge = require('node-forge/lib/forge') +exports.publicKeyLength = forge.pki.ed25519.constants.PUBLIC_KEY_BYTE_LENGTH +exports.privateKeyLength = forge.pki.ed25519.constants.PRIVATE_KEY_BYTE_LENGTH exports.generateKey = async function () { // eslint-disable-line require-await - return nacl.sign.keyPair() + return forge.pki.ed25519.generateKeyPair() } // seed should be a 32 byte uint8array exports.generateKeyFromSeed = async function (seed) { // eslint-disable-line require-await - return nacl.sign.keyPair.fromSeed(seed) + return forge.pki.ed25519.generateKeyPair({ seed }) } exports.hashAndSign = async function (key, msg) { // eslint-disable-line require-await - return Buffer.from(nacl.sign.detached(msg, key)) + return forge.pki.ed25519.sign({ message: msg, privateKey: key }) + // return Buffer.from(nacl.sign.detached(msg, key)) } exports.hashAndVerify = async function (key, sig, msg) { // eslint-disable-line require-await - return nacl.sign.detached.verify(msg, sig, key) + return forge.pki.ed25519.verify({ signature: sig, message: msg, publicKey: key }) } diff --git a/src/keys/index.js b/src/keys/index.js index 7775c71f..a05d8ccf 100644 --- a/src/keys/index.js +++ b/src/keys/index.js @@ -1,9 +1,9 @@ 'use strict' +const { Buffer } = require('buffer') const protobuf = require('protons') const keysPBM = protobuf(require('./keys.proto')) require('node-forge/lib/asn1') -require('node-forge/lib/rsa') require('node-forge/lib/pbe') const forge = require('node-forge/lib/forge') const errcode = require('err-code') diff --git a/src/keys/key-stretcher.js b/src/keys/key-stretcher.js index c9c53665..4870620f 100644 --- a/src/keys/key-stretcher.js +++ b/src/keys/key-stretcher.js @@ -1,5 +1,5 @@ 'use strict' - +const { Buffer } = require('buffer') const errcode = require('err-code') const hmac = require('../hmac') diff --git a/src/keys/rsa-browser.js b/src/keys/rsa-browser.js index ffdd646a..be78717e 100644 --- a/src/keys/rsa-browser.js +++ b/src/keys/rsa-browser.js @@ -1,5 +1,6 @@ 'use strict' +const { Buffer } = require('buffer') const webcrypto = require('../webcrypto') const randomBytes = require('../random-bytes') diff --git a/src/keys/rsa-class.js b/src/keys/rsa-class.js index 6a4775cf..9cce1753 100644 --- a/src/keys/rsa-class.js +++ b/src/keys/rsa-class.js @@ -1,14 +1,14 @@ 'use strict' -const multihashing = require('multihashing-async') +const sha = require('multihashing-async/src/sha') const protobuf = require('protons') -const bs58 = require('bs58') +const multibase = require('multibase') const errcode = require('err-code') const crypto = require('./rsa') const pbm = protobuf(require('./keys.proto')) require('node-forge/lib/sha512') -require('node-forge/lib/pbe') +require('node-forge/lib/ed25519') const forge = require('node-forge/lib/forge') class RsaPublicKey { @@ -40,7 +40,7 @@ class RsaPublicKey { } async hash () { // eslint-disable-line require-await - return multihashing(this.bytes, 'sha2-256') + return sha.multihashing(this.bytes, 'sha2-256') } } @@ -88,7 +88,7 @@ class RsaPrivateKey { } async hash () { // eslint-disable-line require-await - return multihashing(this.bytes, 'sha2-256') + return sha.multihashing(this.bytes, 'sha2-256') } /** @@ -102,7 +102,7 @@ class RsaPrivateKey { */ async id () { const hash = await this.public.hash() - return bs58.encode(hash) + return multibase.encode('base58btc', hash).toString().slice(1) } /** diff --git a/test/aes/aes.spec.js b/test/aes/aes.spec.js index 1c0cdd74..45b4b11f 100644 --- a/test/aes/aes.spec.js +++ b/test/aes/aes.spec.js @@ -2,7 +2,7 @@ /* eslint-disable valid-jsdoc */ /* eslint-env mocha */ 'use strict' - +const { Buffer } = require('buffer') const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect diff --git a/test/fixtures/go-elliptic-key.js b/test/fixtures/go-elliptic-key.js index 8e7d00cd..21dc93e9 100644 --- a/test/fixtures/go-elliptic-key.js +++ b/test/fixtures/go-elliptic-key.js @@ -1,4 +1,5 @@ 'use strict' +const { Buffer } = require('buffer') module.exports = { curve: 'P-256', diff --git a/test/fixtures/go-key-ed25519.js b/test/fixtures/go-key-ed25519.js index 756bf0eb..2fc78302 100644 --- a/test/fixtures/go-key-ed25519.js +++ b/test/fixtures/go-key-ed25519.js @@ -1,4 +1,5 @@ 'use strict' +const { Buffer } = require('buffer') module.exports = { // These were generated in a gore (https://github.com/motemen/gore) repl session: diff --git a/test/fixtures/go-key-rsa.js b/test/fixtures/go-key-rsa.js index 0b260923..7c822f4a 100644 --- a/test/fixtures/go-key-rsa.js +++ b/test/fixtures/go-key-rsa.js @@ -1,5 +1,5 @@ 'use strict' - +const { Buffer } = require('buffer') module.exports = { private: { hash: Buffer.from([ diff --git a/test/fixtures/go-stretch-key.js b/test/fixtures/go-stretch-key.js index 141e7877..8880a8eb 100644 --- a/test/fixtures/go-stretch-key.js +++ b/test/fixtures/go-stretch-key.js @@ -1,5 +1,5 @@ 'use strict' - +const { Buffer } = require('buffer') module.exports = [{ cipher: 'AES-256', hash: 'SHA256', diff --git a/test/fixtures/secp256k1.js b/test/fixtures/secp256k1.js index 78517213..21f72f1f 100644 --- a/test/fixtures/secp256k1.js +++ b/test/fixtures/secp256k1.js @@ -1,5 +1,6 @@ 'use strict' +const { Buffer } = require('buffer') module.exports = { // protobuf marshaled key pair generated with libp2p-crypto-secp256k1 // and marshaled with libp2p-crypto.marshalPublicKey / marshalPrivateKey diff --git a/test/helpers/test-garbage-error-handling.js b/test/helpers/test-garbage-error-handling.js index 75d8ab22..fbe978f9 100644 --- a/test/helpers/test-garbage-error-handling.js +++ b/test/helpers/test-garbage-error-handling.js @@ -1,6 +1,7 @@ /* eslint-env mocha */ 'use strict' +const { Buffer } = require('buffer') const util = require('util') const garbage = [Buffer.from('00010203040506070809', 'hex'), {}, null, false, undefined, true, 1, 0, Buffer.from(''), 'aGVsbG93b3JsZA==', 'helloworld', ''] diff --git a/test/hmac/hmac.spec.js b/test/hmac/hmac.spec.js index 72d53729..75fd9976 100644 --- a/test/hmac/hmac.spec.js +++ b/test/hmac/hmac.spec.js @@ -1,7 +1,7 @@ /* eslint max-nested-callbacks: ["error", 8] */ /* eslint-env mocha */ 'use strict' - +const { Buffer } = require('buffer') const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect diff --git a/test/keys/ed25519.spec.js b/test/keys/ed25519.spec.js index 1fc27160..bfedbec4 100644 --- a/test/keys/ed25519.spec.js +++ b/test/keys/ed25519.spec.js @@ -1,6 +1,7 @@ /* eslint-env mocha */ 'use strict' +const { Buffer } = require('buffer') const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect diff --git a/test/keys/rsa.spec.js b/test/keys/rsa.spec.js index dc8db156..cc4daecd 100644 --- a/test/keys/rsa.spec.js +++ b/test/keys/rsa.spec.js @@ -2,6 +2,7 @@ /* eslint-env mocha */ 'use strict' +const { Buffer } = require('buffer') const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect diff --git a/test/util.spec.js b/test/util.spec.js index 5c362d13..cd7832ed 100644 --- a/test/util.spec.js +++ b/test/util.spec.js @@ -3,6 +3,7 @@ 'use strict' const chai = require('chai') +const { Buffer } = require('buffer') const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) From 825ba147fb7b6978faf64d0bc0a3e22c69eaa067 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Mon, 16 Mar 2020 12:00:43 +0000 Subject: [PATCH 2/5] fix: reduce bundle size --- .aegir.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.aegir.js b/.aegir.js index 25fbe20f..1ad9b3f6 100644 --- a/.aegir.js +++ b/.aegir.js @@ -1,3 +1,3 @@ module.exports = { - bundlesize: { maxSize: '155kB' } + bundlesize: { maxSize: '123kB' } } From 822b5771ceb179b24552c565744d6e7ac35bc8e6 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Mon, 16 Mar 2020 18:18:34 +0000 Subject: [PATCH 3/5] fix: use new secp --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 97d4f9e6..4dfbca52 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "err-code": "^2.0.0", "iso-random-stream": "^1.1.0", "keypair": "^1.0.1", - "libp2p-crypto-secp256k1": "~0.4.0", + "libp2p-crypto-secp256k1": "libp2p/js-libp2p-crypto-secp256k1#fix/add-buffer", "multibase": "^0.6.0", "multihashing-async": "^0.8.1", "node-forge": "~0.9.1", From adf57cb0a36841bfbbde368e188d375eae014a31 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Mon, 16 Mar 2020 18:21:25 +0000 Subject: [PATCH 4/5] fix: bundle size --- .aegir.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.aegir.js b/.aegir.js index 1ad9b3f6..3faa51b2 100644 --- a/.aegir.js +++ b/.aegir.js @@ -1,3 +1,3 @@ module.exports = { - bundlesize: { maxSize: '123kB' } + bundlesize: { maxSize: '124kB' } } From 0a73c6a1374c44768068a7918515250aa2b448da Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Wed, 18 Mar 2020 13:20:23 +0000 Subject: [PATCH 5/5] chore: update secp Co-Authored-By: Jacob Heun --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4dfbca52..e94108e5 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "err-code": "^2.0.0", "iso-random-stream": "^1.1.0", "keypair": "^1.0.1", - "libp2p-crypto-secp256k1": "libp2p/js-libp2p-crypto-secp256k1#fix/add-buffer", + "libp2p-crypto-secp256k1": "^0.4.2", "multibase": "^0.6.0", "multihashing-async": "^0.8.1", "node-forge": "~0.9.1",