From b44e15fbb8f3a66d69066a93a4cebeb20614b27f Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Sat, 26 Jan 2019 14:22:20 +0100 Subject: [PATCH] feat: rsa key wrap/unwrap --- lib/jwa/index.js | 28 +++++++++++++++++++++++++++- lib/jwa/rsaes.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 lib/jwa/rsaes.js diff --git a/lib/jwa/index.js b/lib/jwa/index.js index d568d989..bace3dbd 100644 --- a/lib/jwa/index.js +++ b/lib/jwa/index.js @@ -2,14 +2,20 @@ const { TODO } = require('../errors') const JWA = { sign: new Map(), - verify: new Map() + verify: new Map(), + wrapKey: new Map(), + unwrapKey: new Map(), } +// sign, verify require('./hmac')(JWA) require('./ecdsa')(JWA) require('./rsassa_pss')(JWA) require('./rsassa_pkcs1')(JWA) +// wrapKey, unwrapKey +require('./rsaes')(JWA) + module.exports = { sign: (alg, key, payload) => { if (!JWA.sign.has(alg)) { @@ -30,5 +36,25 @@ module.exports = { } return JWA.verify.get(alg)(key, payload, signature) + }, + wrapKey: (alg, key, payload) => { + if (!JWA.wrapKey.has(alg)) { + throw new TODO(`wrapKey alg ${alg} not implemented`) + } + if (!key.algorithms('wrapKey').has(alg)) { + throw new TODO(`the key does not support ${alg} wrapKey algorithm`) + } + + return JWA.sign.get(alg)(key, payload) + }, + unwrapKey: (alg, key, payload) => { + if (!JWA.unwrapKey.has(alg)) { + throw new TODO(`unwrapKey alg ${alg} not implemented`) + } + if (!key.algorithms('unwrapKey').has(alg)) { + throw new TODO(`the key does not support ${alg} unwrapKey algorithm`) + } + + return JWA.unwrapKey.get(alg)(key, payload) } } diff --git a/lib/jwa/rsaes.js b/lib/jwa/rsaes.js new file mode 100644 index 00000000..d91e7ca4 --- /dev/null +++ b/lib/jwa/rsaes.js @@ -0,0 +1,31 @@ +const { strict: assert } = require('assert') +const { publicEncrypt, privateDecrypt, constants } = require('crypto') + +const resolvePadding = (alg) => { + switch (alg) { + case 'RSA-OAEP': + return constants.RSA_PKCS1_OAEP_PADDING + case 'RSA1_5': + return constants.RSA_PKCS1_PADDING + } +} + +const wrapKey = (padding, { keyObject }, payload) => { + return publicEncrypt({ key: keyObject, padding }, payload) +} + +const unwrapKey = (padding, { keyObject }, payload) => { + return privateDecrypt({ key: keyObject, padding }, payload) +} + +module.exports = (JWA) => { + ['RSA1_5', 'RSA-OAEP'].forEach((jwaAlg) => { + const padding = resolvePadding(jwaAlg) + + assert(!JWA.wrapKey.has(jwaAlg), `wrapKey alg ${jwaAlg} already registered`) + assert(!JWA.unwrapKey.has(jwaAlg), `unwrapKey alg ${jwaAlg} already registered`) + + JWA.wrapKey.set(jwaAlg, wrapKey.bind(undefined, padding)) + JWA.unwrapKey.set(jwaAlg, unwrapKey.bind(undefined, padding)) + }) +}