From eb467f94f0f3b4f5deee8cd37283b4e8ddfad855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Fri, 12 Jul 2019 18:53:46 +0200 Subject: [PATCH 01/11] feat: add (rsa)pubKey.encrypt and (rsa)privKey.decrypt nodeJS only for now --- src/keys/rsa-class.js | 8 ++++++-- src/keys/rsa.js | 8 ++++++++ test/keys/rsa.spec.js | 7 +++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/keys/rsa-class.js b/src/keys/rsa-class.js index 84ad38bd..1046eba5 100644 --- a/src/keys/rsa-class.js +++ b/src/keys/rsa-class.js @@ -31,8 +31,8 @@ class RsaPublicKey { }) } - encrypt (bytes) { - return this._key.encrypt(bytes, 'RSAES-PKCS1-V1_5') + async encrypt (bytes) { + return crypto.encrypt(this._key, bytes) } equals (key) { @@ -68,6 +68,10 @@ class RsaPrivateKey { return new RsaPublicKey(this._publicKey) } + async decrypt (bytes) { + return crypto.decrypt(this._key, bytes) + } + marshal () { return crypto.utils.jwkToPkcs1(this._key) } diff --git a/src/keys/rsa.js b/src/keys/rsa.js index 019760a7..f7c0b35b 100644 --- a/src/keys/rsa.js +++ b/src/keys/rsa.js @@ -68,3 +68,11 @@ exports.hashAndVerify = async function (key, sig, msg) { // eslint-disable-line const pem = jwkToPem(key) return verify.verify(pem, sig) } + +exports.encrypt = async function (key, bytes) { + return crypto.publicEncrypt(jwkToPem(key), bytes) +} + +exports.decrypt = async function (key, bytes) { + return crypto.privateDecrypt(jwkToPem(key), bytes) +} diff --git a/test/keys/rsa.spec.js b/test/keys/rsa.spec.js index 175b1443..c3b47be5 100644 --- a/test/keys/rsa.spec.js +++ b/test/keys/rsa.spec.js @@ -80,6 +80,13 @@ describe('RSA', function () { expect(valid).to.be.eql(true) }) + it('encrypt and decrypt', async () => { + const data = Buffer.from('hello world') + const enc = await key.public.encrypt(data) + const dec = await key.decrypt(enc) + expect(dec).to.be.eql(data) + }) + it('fails to verify for different data', async () => { const data = Buffer.from('hello world') const sig = await key.sign(data) From 1218eab7cd8f0fb6e00ac63fb7db543e9eccf03c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Fri, 12 Jul 2019 18:53:56 +0200 Subject: [PATCH 02/11] feat: browser enc/dec --- src/keys/rsa-browser.js | 44 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/keys/rsa-browser.js b/src/keys/rsa-browser.js index be268fb1..244e513a 100644 --- a/src/keys/rsa-browser.js +++ b/src/keys/rsa-browser.js @@ -120,3 +120,47 @@ function derivePublicFromPrivate (jwKey) { ['verify'] ) } + +exports.encrypt = async function (key, msg) { + key = Object.assign({}, key) + key.key_ops = ['encrypt'] + + return webcrypto.subtle.importKey( + 'jwk', + key, + { + name: 'RSA-OAEP', + hash: { name: 'SHA-256' } + }, + false, + ['encrypt'] + ).then((publicKey) => { + return webcrypto.subtle.encrypt( + { name: 'RSA-OEAP' }, + publicKey, + Uint8Array.from(msg) + ) + }).then((enc) => Buffer.from(enc)) +} + +exports.decrypt = async function (key, msg) { + key = Object.assign({}, key) + key.key_ops = ['decrypt'] + + return webcrypto.subtle.importKey( + 'jwk', + key, + { + name: 'RSA-OAEP', + hash: { name: 'SHA-256' } + }, + false, + ['decrypt'] + ).then((privateKey) => { + return webcrypto.subtle.decrypt( + { name: 'RSA-OAEP' }, + privateKey, + Uint8Array.from(msg) + ) + }).then((dec) => Buffer.from(dec)) +} From 152648af7645f98ce163c6d082615b115b45bc8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Wed, 23 Oct 2019 12:55:43 +0200 Subject: [PATCH 03/11] fix: browser rsa enc/dec --- package.json | 2 +- src/keys/rsa-browser.js | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 7137d1d7..4896f833 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "keypair": "^1.0.1", "libp2p-crypto-secp256k1": "~0.4.0", "multihashing-async": "~0.7.0", - "node-forge": "~0.8.5", + "node-forge": "^0.9.1", "pem-jwk": "^2.0.0", "protons": "^1.0.1", "rsa-pem-to-jwk": "^1.1.3", diff --git a/src/keys/rsa-browser.js b/src/keys/rsa-browser.js index 244e513a..ec6bce22 100644 --- a/src/keys/rsa-browser.js +++ b/src/keys/rsa-browser.js @@ -121,8 +121,33 @@ function derivePublicFromPrivate (jwKey) { ) } +// bloody dark magic. webcrypto's why. + +/* + +Explanation: + - Convert JWK to PEM + - Load PEM with nodeForge + - Convert msg buffer to nodeForge buffer + - Convert resulting nodeForge buffer to buffer + +*/ + +const forge = require('node-forge') +const pki = forge.pki +const jwkToPem = require('pem-jwk').jwk2pem +function convertKey (key, pub, msg, handle) { + const pem = jwkToPem(key) + const fkey = pki[pub ? 'publicKeyFromPem' : 'privateKeyFromPem'](pem) + const fmsg = forge.util.hexToBytes(Buffer.from(msg).toString('hex')) + const fomsg = handle(fmsg, fkey) + return Buffer.from(forge.util.bytesToHex(fomsg), 'hex') +} + exports.encrypt = async function (key, msg) { - key = Object.assign({}, key) + return convertKey(key, true, msg, (msg, key) => key.encrypt(msg)) + + /* key = Object.assign({}, key) key.key_ops = ['encrypt'] return webcrypto.subtle.importKey( @@ -140,11 +165,13 @@ exports.encrypt = async function (key, msg) { publicKey, Uint8Array.from(msg) ) - }).then((enc) => Buffer.from(enc)) + }).then((enc) => Buffer.from(enc)) */ } exports.decrypt = async function (key, msg) { - key = Object.assign({}, key) + return convertKey(key, false, msg, (msg, key) => key.decrypt(msg)) + + /* key = Object.assign({}, key) key.key_ops = ['decrypt'] return webcrypto.subtle.importKey( @@ -162,5 +189,5 @@ exports.decrypt = async function (key, msg) { privateKey, Uint8Array.from(msg) ) - }).then((dec) => Buffer.from(dec)) + }).then((dec) => Buffer.from(dec)) */ } From 6af625dbaec01366be7771fef5a93cd2a70b41b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Wed, 23 Oct 2019 12:57:23 +0200 Subject: [PATCH 04/11] refactor: cleanup --- package.json | 2 +- src/keys/rsa-browser.js | 49 +++++------------------------------------ 2 files changed, 6 insertions(+), 45 deletions(-) diff --git a/package.json b/package.json index 4896f833..abc1dd96 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "keypair": "^1.0.1", "libp2p-crypto-secp256k1": "~0.4.0", "multihashing-async": "~0.7.0", - "node-forge": "^0.9.1", + "node-forge": "~0.9.1", "pem-jwk": "^2.0.0", "protons": "^1.0.1", "rsa-pem-to-jwk": "^1.1.3", diff --git a/src/keys/rsa-browser.js b/src/keys/rsa-browser.js index ec6bce22..525ec1fe 100644 --- a/src/keys/rsa-browser.js +++ b/src/keys/rsa-browser.js @@ -121,10 +121,11 @@ function derivePublicFromPrivate (jwKey) { ) } -// bloody dark magic. webcrypto's why. - /* +RSA encryption/decryption for the browser with webcrypto workarround +"bloody dark magic. webcrypto's why." + Explanation: - Convert JWK to PEM - Load PEM with nodeForge @@ -144,50 +145,10 @@ function convertKey (key, pub, msg, handle) { return Buffer.from(forge.util.bytesToHex(fomsg), 'hex') } -exports.encrypt = async function (key, msg) { +exports.encrypt = function (key, msg) { return convertKey(key, true, msg, (msg, key) => key.encrypt(msg)) - - /* key = Object.assign({}, key) - key.key_ops = ['encrypt'] - - return webcrypto.subtle.importKey( - 'jwk', - key, - { - name: 'RSA-OAEP', - hash: { name: 'SHA-256' } - }, - false, - ['encrypt'] - ).then((publicKey) => { - return webcrypto.subtle.encrypt( - { name: 'RSA-OEAP' }, - publicKey, - Uint8Array.from(msg) - ) - }).then((enc) => Buffer.from(enc)) */ } -exports.decrypt = async function (key, msg) { +exports.decrypt = function (key, msg) { return convertKey(key, false, msg, (msg, key) => key.decrypt(msg)) - - /* key = Object.assign({}, key) - key.key_ops = ['decrypt'] - - return webcrypto.subtle.importKey( - 'jwk', - key, - { - name: 'RSA-OAEP', - hash: { name: 'SHA-256' } - }, - false, - ['decrypt'] - ).then((privateKey) => { - return webcrypto.subtle.decrypt( - { name: 'RSA-OAEP' }, - privateKey, - Uint8Array.from(msg) - ) - }).then((dec) => Buffer.from(dec)) */ } From 10bfcf6113d8e3fb47b7d1f6603621af527a472d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Wed, 23 Oct 2019 13:04:55 +0200 Subject: [PATCH 05/11] fix: lint --- src/keys/rsa-class.js | 4 ++-- src/keys/rsa.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/keys/rsa-class.js b/src/keys/rsa-class.js index 1046eba5..bc9289ab 100644 --- a/src/keys/rsa-class.js +++ b/src/keys/rsa-class.js @@ -31,7 +31,7 @@ class RsaPublicKey { }) } - async encrypt (bytes) { + encrypt (bytes) { return crypto.encrypt(this._key, bytes) } @@ -68,7 +68,7 @@ class RsaPrivateKey { return new RsaPublicKey(this._publicKey) } - async decrypt (bytes) { + decrypt (bytes) { return crypto.decrypt(this._key, bytes) } diff --git a/src/keys/rsa.js b/src/keys/rsa.js index f7c0b35b..3557e3c9 100644 --- a/src/keys/rsa.js +++ b/src/keys/rsa.js @@ -69,10 +69,10 @@ exports.hashAndVerify = async function (key, sig, msg) { // eslint-disable-line return verify.verify(pem, sig) } -exports.encrypt = async function (key, bytes) { +exports.encrypt = function (key, bytes) { return crypto.publicEncrypt(jwkToPem(key), bytes) } -exports.decrypt = async function (key, bytes) { +exports.decrypt = function (key, bytes) { return crypto.privateDecrypt(jwkToPem(key), bytes) } From ebb656db73e07ef51b05c46bfc6af4d7b1fbc71e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Wed, 23 Oct 2019 13:33:48 +0200 Subject: [PATCH 06/11] fix: use direct buffers instead of converting to hex --- src/keys/rsa-browser.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/keys/rsa-browser.js b/src/keys/rsa-browser.js index 525ec1fe..7b524a33 100644 --- a/src/keys/rsa-browser.js +++ b/src/keys/rsa-browser.js @@ -129,8 +129,8 @@ RSA encryption/decryption for the browser with webcrypto workarround Explanation: - Convert JWK to PEM - Load PEM with nodeForge - - Convert msg buffer to nodeForge buffer - - Convert resulting nodeForge buffer to buffer + - Convert msg buffer to nodeForge buffer: it's already uint8array, so do nothing + - Convert resulting nodeForge buffer to buffer: it returns a binary string, turn that into a uint8array */ @@ -140,9 +140,8 @@ const jwkToPem = require('pem-jwk').jwk2pem function convertKey (key, pub, msg, handle) { const pem = jwkToPem(key) const fkey = pki[pub ? 'publicKeyFromPem' : 'privateKeyFromPem'](pem) - const fmsg = forge.util.hexToBytes(Buffer.from(msg).toString('hex')) - const fomsg = handle(fmsg, fkey) - return Buffer.from(forge.util.bytesToHex(fomsg), 'hex') + const fomsg = handle(Buffer.from(msg), fkey) + return Buffer.from(fomsg, 'binary') } exports.encrypt = function (key, msg) { From dbf348913960e6c9bf729dc4966f36e6029317bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Wed, 23 Oct 2019 14:00:11 +0200 Subject: [PATCH 07/11] fix: padding error --- src/keys/rsa-browser.js | 7 ++++--- src/keys/rsa.js | 6 ++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/keys/rsa-browser.js b/src/keys/rsa-browser.js index 7b524a33..b17f62e3 100644 --- a/src/keys/rsa-browser.js +++ b/src/keys/rsa-browser.js @@ -129,8 +129,8 @@ RSA encryption/decryption for the browser with webcrypto workarround Explanation: - Convert JWK to PEM - Load PEM with nodeForge - - Convert msg buffer to nodeForge buffer: it's already uint8array, so do nothing - - Convert resulting nodeForge buffer to buffer: it returns a binary string, turn that into a uint8array + - Convert msg buffer to nodeForge buffer: ByteBuffer is a "binary-string backed buffer", so let's make our buffer a binary string + - Convert resulting nodeForge buffer to buffer: it returns a binary string, turn that into a uint8array(buffer) */ @@ -140,7 +140,8 @@ const jwkToPem = require('pem-jwk').jwk2pem function convertKey (key, pub, msg, handle) { const pem = jwkToPem(key) const fkey = pki[pub ? 'publicKeyFromPem' : 'privateKeyFromPem'](pem) - const fomsg = handle(Buffer.from(msg), fkey) + const fmsg = Buffer.from(msg).toString('binary') + const fomsg = handle(fmsg, fkey) return Buffer.from(fomsg, 'binary') } diff --git a/src/keys/rsa.js b/src/keys/rsa.js index 3557e3c9..06605a32 100644 --- a/src/keys/rsa.js +++ b/src/keys/rsa.js @@ -69,10 +69,12 @@ exports.hashAndVerify = async function (key, sig, msg) { // eslint-disable-line return verify.verify(pem, sig) } +const padding = crypto.constants.RSA_PKCS1_PADDING + exports.encrypt = function (key, bytes) { - return crypto.publicEncrypt(jwkToPem(key), bytes) + return crypto.publicEncrypt({ key: jwkToPem(key), padding }, bytes) } exports.decrypt = function (key, bytes) { - return crypto.privateDecrypt(jwkToPem(key), bytes) + return crypto.privateDecrypt({ key: jwkToPem(key), padding }, bytes) } From b922f7fc46980e1580011cfde383e273f5dd43d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Wed, 23 Oct 2019 14:03:14 +0200 Subject: [PATCH 08/11] test: add interop test --- test/keys/rsa.spec.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/keys/rsa.spec.js b/test/keys/rsa.spec.js index c3b47be5..22be3bc1 100644 --- a/test/keys/rsa.spec.js +++ b/test/keys/rsa.spec.js @@ -87,6 +87,19 @@ describe('RSA', function () { expect(dec).to.be.eql(data) }) + it('encrypt decrypt browser/node interop', async () => { + const id = await crypto.keys.unmarshalPrivateKey(Buffer.from('CAASqAkwggSkAgEAAoIBAQCk0O+6oNRxhcdZe2GxEDrFBkDV4TZFZnp2ly/dL1cGMBql/8oXPZgei6h7+P5zzfDq2YCfwbjbf0IVY1AshRl6B5VGE1WS+9p1y1OZxJf5os6V1ENnTi6FTcyuBl4BN8dmIKOif0hqgqflaT5OhfYZDXfbJyVQj4vb2+Stu2Xpph3nwqAnTw/7GC/7jrt2Cq6Tu1PoZi36wSwEPYW3eQ1HAYxZjTYYDXl2iyHygnTcbkGRwAQ7vjk+mW7u60zyoolCm9f6Y7c/orJ33DDUocbaGJLlHcfd8bioBwaZy/2m7q43X8pQs0Q1/iwUt0HHZj1YARmHKbh0zR31ciFiV37dAgMBAAECggEADtJBNKnA4QKURj47r0YT2uLwkqtBi6UnDyISalQXAdXyl4n0nPlrhBewC5H9I+HZr+zmTbeIjaiYgz7el1pSy7AB4v7bG7AtWZlyx6mvtwHGjR+8/f3AXjl8Vgv5iSeAdXUq8fJ7SyS7v3wi38HZOzCEXj9bci6ud5ODMYJgLE4gZD0+i1+/V9cpuYfGpS/gLTLEMQLiw/9o8NSZ7sAnxg0UlYhotqaQY23hvXPBOe+0oa95zl2n6XTxCafa3dQl/B6CD1tUq9dhbQew4bxqMq/mhRO9pREEqZ083Uh+u4PTc1BeHgIQaS864pHPb+AY1F7KDvPtHhdojnghp8d70QKBgQDeRYFxo6sd04ohY86Z/i9icVYIyCvfXAKnaMKeGUjK7ou6sDJwFX8W97+CzXpZ/vffsk/l5GGhC50KqrITxHAy/h5IjyDODfps7NMIp0Dm9sO4PWibbw3OOVBRc8w3b3i7I8MrUUA1nLHE1T1HA1rKOTz5jYhE0fi9XKiT1ciKOQKBgQC903w+n9y7M7eaMW7Z5/13kZ7PS3HlM681eaPrk8J4J+c6miFF40/8HOsmarS38v0fgTeKkriPz5A7aLzRHhSiOnp350JNM6c3sLwPEs2qx/CRuWWx1rMERatfDdUH6mvlK6QHu0QgSfQR27EO6a6XvVSJXbvFmimjmtIaz/IpxQKBgQDWJ9HYVAGC81abZTaiWK3/A4QJYhQjWNuVwPICsgnYvI4Uib+PDqcs0ffLZ38DRw48kek5bxpBuJbOuDhro1EXUJCNCJpq7jzixituovd9kTRyR3iKii2bDM2+LPwOTXDdnk9lZRugjCEbrPkleq33Ob7uEtfAty4aBTTHe6uEwQKBgQCB+2q8RyMSXNuADhFlzOFXGrOwJm0bEUUMTPrduRQUyt4e1qOqA3klnXe3mqGcxBpnlEe/76/JacvNom6Ikxx16a0qpYRU8OWz0KU1fR6vrrEgV98241k5t6sdL4+MGA1Bo5xyXtzLb1hdUh3vpDwVU2OrnC+To3iXus/b5EBiMQKBgEI1OaBcFiyjgLGEyFKoZbtzH1mdatTExfrAQqCjOVjQByoMpGhHTXwEaosvyYu63Pa8AJPT7juSGaiKYEJFcXO9BiNyVfmQiqSHJcYeuh+fmO9IlHRHgy5xaIIC00AHS2vC/gXwmXAdPis6BZqDJeiCuOLWJ94QXn8JBT8IgGAI', 'base64')) + + const msg = Buffer.from('hello') + + // browser + const dec1 = await id.decrypt(Buffer.from('YRFUDx8UjbWSfDS84cDA4WowaaOmd1qFNAv5QutodCKYb9uPtU/tDiAvJzOGu5DCJRo2J0l/35P2weiB4/C2Cb1aZgXKMx/QQC+2jSJiymhqcZaYerjTvkCFwkjCaqthoVo/YXxsaFZ1q7bdTZUDH1TaJR7hWfSyzyPcA8c0w43MIsw16pY8ZaPSclvnCwhoTg1JGjMk6te3we7+wR8QU7VrPhs54mZWxrpu3NQ8xZ6xQqIedsEiNhBUccrCSzYghgsP0Ae/8iKyGyl3U6IegsJNn8jcocvzOJrmU03rgIFPjvuBdaqB38xDSTjbA123KadB28jNoSZh18q/yH3ZIg==', 'base64')) + expect(dec1).to.be.eql(msg) + // node + const dec2 = await id.decrypt(Buffer.from('e6yxssqXsWc27ozDy0PGKtMkCS28KwFyES2Ijz89yiz+w6bSFkNOhHPKplpPzgQEuNoUGdbseKlJFyRYHjIT8FQFBHZM8UgSkgoimbY5on4xSxXs7E5/+twjqKdB7oNveTaTf7JCwaeUYnKSjbiYFEawtMiQE91F8sTT7TmSzOZ48tUhnddAAZ3Ac/O3Z9MSAKOCDipi+JdZtXRT8KimGt36/7hjjosYmPuHR1Xy/yMTL6SMbXtBM3yAuEgbQgP+q/7kHMHji3/JvTpYdIUU+LVtkMusXNasRA+UWG2zAht18vqjFMsm9JTiihZw9jRHD4vxAhf75M992tnC+0ZuQg==', 'base64')) + expect(dec2).to.be.eql(msg) + }) + it('fails to verify for different data', async () => { const data = Buffer.from('hello world') const sig = await key.sign(data) From 615a023f21a741c6f82b22f245abad02ee45a692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Fri, 25 Oct 2019 12:58:41 +0200 Subject: [PATCH 09/11] feat: use forge to convert jwk2forge --- src/keys/jwk2pem.js | 42 +++++++++++++++++++++++++++++++++++++++++ src/keys/rsa-browser.js | 11 ++++------- 2 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 src/keys/jwk2pem.js diff --git a/src/keys/jwk2pem.js b/src/keys/jwk2pem.js new file mode 100644 index 00000000..9dd2c00f --- /dev/null +++ b/src/keys/jwk2pem.js @@ -0,0 +1,42 @@ +'use strict' + +const forge = { + util: require('node-forge/lib/util'), + pki: require('node-forge/lib/pki'), + jsbn: require('node-forge/lib/jsbn') +} + +function base64urlToBigInteger (str) { + var bytes = forge.util.decode64( + (str + '==='.slice((str.length + 3) % 4)) + .replace(/-/g, '+') + .replace(/_/g, '/')) + return new forge.jsbn.BigInteger(forge.util.bytesToHex(bytes), 16) +} + +function convert (key, types) { + return types.map(t => base64urlToBigInteger(key[t])) +} + +function jwk2priv (key) { + return forge.pki.setRsaPrivatKey(...convert(key, ['n', 'e', 'd', 'p', 'q', 'dP', 'dQ', 'qInv'])) +} + +function jwk2privPem (key) { + return forge.pki.privateKeyToPem(jwk2priv(key)) +} + +function jwk2pub (key) { + return forge.pki.setRsaPublicKey(...convert(key, ['n', 'e'])) +} + +function jwk2pubPem (key) { + return forge.pki.publicKeyToPem(jwk2pub(key)) +} + +module.exports = { + jwk2pub, + jwk2pubPem, + jwk2priv, + jwk2privPem +} diff --git a/src/keys/rsa-browser.js b/src/keys/rsa-browser.js index b17f62e3..ffdd646a 100644 --- a/src/keys/rsa-browser.js +++ b/src/keys/rsa-browser.js @@ -127,19 +127,16 @@ RSA encryption/decryption for the browser with webcrypto workarround "bloody dark magic. webcrypto's why." Explanation: - - Convert JWK to PEM - - Load PEM with nodeForge + - Convert JWK to nodeForge - Convert msg buffer to nodeForge buffer: ByteBuffer is a "binary-string backed buffer", so let's make our buffer a binary string - Convert resulting nodeForge buffer to buffer: it returns a binary string, turn that into a uint8array(buffer) */ -const forge = require('node-forge') -const pki = forge.pki -const jwkToPem = require('pem-jwk').jwk2pem +const { jwk2pub, jwk2priv } = require('./jwk2pem') + function convertKey (key, pub, msg, handle) { - const pem = jwkToPem(key) - const fkey = pki[pub ? 'publicKeyFromPem' : 'privateKeyFromPem'](pem) + const fkey = pub ? jwk2pub(key) : jwk2priv(key) const fmsg = Buffer.from(msg).toString('binary') const fomsg = handle(fmsg, fkey) return Buffer.from(fomsg, 'binary') From 5164b2908a31530a8e660b5574c9e0057881bd75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Fri, 25 Oct 2019 13:05:05 +0200 Subject: [PATCH 10/11] fix: jwk var naming --- src/keys/jwk2pem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/keys/jwk2pem.js b/src/keys/jwk2pem.js index 9dd2c00f..f50791be 100644 --- a/src/keys/jwk2pem.js +++ b/src/keys/jwk2pem.js @@ -19,7 +19,7 @@ function convert (key, types) { } function jwk2priv (key) { - return forge.pki.setRsaPrivatKey(...convert(key, ['n', 'e', 'd', 'p', 'q', 'dP', 'dQ', 'qInv'])) + return forge.pki.setRsaPrivateKey(...convert(key, ['n', 'e', 'd', 'p', 'q', 'dp', 'dq', 'qi'])) } function jwk2privPem (key) { From 1c378be60fdad31fbc159c617f804d6af6b1e95d Mon Sep 17 00:00:00 2001 From: Jacob Heun Date: Thu, 24 Oct 2019 18:16:41 +0200 Subject: [PATCH 11/11] chore: remove commitlint chore: update deps chore: add bundlesize to ci --- .aegir.js | 3 +++ .travis.yml | 2 +- package.json | 13 ++++++------- src/keys/index.js | 2 +- src/keys/key-stretcher.js | 4 ++-- src/util.js | 2 +- test/helpers/test-garbage-error-handling.js | 2 +- test/keys/ephemeral-keys.spec.js | 2 +- test/util.spec.js | 2 +- 9 files changed, 17 insertions(+), 15 deletions(-) create mode 100644 .aegir.js diff --git a/.aegir.js b/.aegir.js new file mode 100644 index 00000000..25fbe20f --- /dev/null +++ b/.aegir.js @@ -0,0 +1,3 @@ +module.exports = { + bundlesize: { maxSize: '155kB' } +} diff --git a/.travis.yml b/.travis.yml index 88040e7f..00e0e5fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ jobs: include: - stage: check script: - - npx aegir commitlint --travis + - npx aegir build --bundlesize - npx aegir dep-check - npm run lint diff --git a/package.json b/package.json index abc1dd96..ad300c5d 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "release-minor": "aegir release --type minor", "release-major": "aegir release --type major", "coverage": "aegir coverage --ignore src/keys/keys.proto.js", - "size": "bundlesize -f dist/index.min.js -s 139kB" + "size": "aegir build --bundlesize" }, "keywords": [ "IPFS", @@ -36,7 +36,7 @@ "license": "MIT", "dependencies": { "asmcrypto.js": "^2.3.2", - "asn1.js": "^5.0.1", + "asn1.js": "^5.2.0", "bn.js": "^5.0.0", "browserify-aes": "^1.2.0", "bs58": "^4.0.1", @@ -44,22 +44,21 @@ "iso-random-stream": "^1.1.0", "keypair": "^1.0.1", "libp2p-crypto-secp256k1": "~0.4.0", - "multihashing-async": "~0.7.0", + "multihashing-async": "~0.8.0", "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.0" + "ursa-optional": "~0.10.1" }, "devDependencies": { - "aegir": "^19.0.5", + "aegir": "^20.4.1", "benchmark": "^2.1.4", - "bundlesize": "~0.18.0", "chai": "^4.2.0", "chai-string": "^1.5.0", "dirty-chai": "^2.0.1", - "sinon": "^7.3.2" + "sinon": "^7.5.0" }, "engines": { "node": ">=10.0.0", diff --git a/src/keys/index.js b/src/keys/index.js index 205d1086..7775c71f 100644 --- a/src/keys/index.js +++ b/src/keys/index.js @@ -25,7 +25,7 @@ const ErrMissingSecp256K1 = { } function typeToKey (type) { - let key = supportedKeys[type.toLowerCase()] + const key = supportedKeys[type.toLowerCase()] if (!key) { const supported = Object.keys(supportedKeys).join(' / ') throw errcode(new Error(`invalid or unsupported key type ${type}. Must be ${supported}`), 'ERR_UNSUPPORTED_KEY_TYPE') diff --git a/src/keys/key-stretcher.js b/src/keys/key-stretcher.js index cca81781..c9c53665 100644 --- a/src/keys/key-stretcher.js +++ b/src/keys/key-stretcher.js @@ -29,7 +29,7 @@ module.exports = async (cipherType, hash, secret) => { } if (!hash) { - throw errcode(new Error(`missing hash type`), 'ERR_MISSING_HASH_TYPE') + throw errcode(new Error('missing hash type'), 'ERR_MISSING_HASH_TYPE') } const cipherKeySize = cipher.keySize @@ -41,7 +41,7 @@ module.exports = async (cipherType, hash, secret) => { const m = await hmac.create(hash, secret) let a = await m.digest(seed) - let result = [] + const result = [] let j = 0 while (j < resultLength) { diff --git a/src/util.js b/src/util.js index e5f7b6b1..3624bfe8 100644 --- a/src/util.js +++ b/src/util.js @@ -6,7 +6,7 @@ const BN = require('asn1.js').bignum // Adapted from https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#appendix-C exports.toBase64 = function toBase64 (bn, len) { // if len is defined then the bytes are leading-0 padded to the length - let s = bn.toArrayLike(Buffer, 'be', len).toString('base64') + const s = bn.toArrayLike(Buffer, 'be', len).toString('base64') return s .replace(/(=*)$/, '') // Remove any trailing '='s diff --git a/test/helpers/test-garbage-error-handling.js b/test/helpers/test-garbage-error-handling.js index 324789c3..75d8ab22 100644 --- a/test/helpers/test-garbage-error-handling.js +++ b/test/helpers/test-garbage-error-handling.js @@ -14,7 +14,7 @@ function doTests (fncName, fnc, num, skipBuffersAndStrings) { // skip this garbage because it's a buffer or a string and we were told do do that return } - let args = [] + const args = [] for (let i = 0; i < num; i++) { args.push(garbage) } diff --git a/test/keys/ephemeral-keys.spec.js b/test/keys/ephemeral-keys.spec.js index 5ad66452..57fcb00e 100644 --- a/test/keys/ephemeral-keys.spec.js +++ b/test/keys/ephemeral-keys.spec.js @@ -61,7 +61,7 @@ describe('generateEphemeralKeyPair', () => { }) }) - it(`handles bad curve name`, async () => { + it('handles bad curve name', async () => { try { await crypto.keys.generateEphemeralKeyPair('bad name') } catch (err) { diff --git a/test/util.spec.js b/test/util.spec.js index bf66ccd7..3688861b 100644 --- a/test/util.spec.js +++ b/test/util.spec.js @@ -24,7 +24,7 @@ describe('Util', () => { }) it('toBase64 zero padding', (done) => { - let bnpad = new BN('ff', 16) + const bnpad = new BN('ff', 16) expect(util.toBase64(bnpad, 2)).to.eql('AP8') done() })