diff --git a/src/keys/jwk2pem.js b/src/keys/jwk2pem.js new file mode 100644 index 0000000..9dd2c00 --- /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 b17f62e..ffdd646 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')