UNPKG

2.11 kBJavaScriptView Raw
1const { pbkdf2Sync: pbkdf2, randomBytes } = require('crypto')
2
3const { KEYOBJECT } = require('../help/consts')
4const base64url = require('../help/base64url')
5
6const SALT_LENGTH = 16
7const NULL_BUFFER = Buffer.alloc(1, 0)
8
9const concatSalt = (alg, p2s) => {
10 return Buffer.concat([
11 Buffer.from(alg, 'utf8'),
12 NULL_BUFFER,
13 p2s
14 ])
15}
16
17const wrapKey = (keylen, sha, concat, wrap, { [KEYOBJECT]: keyObject }, payload) => {
18 // Note that if password-based encryption is used for multiple
19 // recipients, it is expected that each recipient use different values
20 // for the PBES2 parameters "p2s" and "p2c".
21 // here we generate p2c between 2048 and 4096 and random p2s
22 const p2c = Math.floor((Math.random() * 2049) + 2048)
23 const p2s = randomBytes(SALT_LENGTH)
24 const salt = concat(p2s)
25
26 const derivedKey = pbkdf2(keyObject.export(), salt, p2c, keylen, sha)
27
28 const result = wrap({ [KEYOBJECT]: derivedKey }, payload)
29 result.header = result.header || {}
30 Object.assign(result.header, { p2c, p2s: base64url.encodeBuffer(p2s) })
31
32 return result
33}
34
35const unwrapKey = (keylen, sha, concat, unwrap, { [KEYOBJECT]: keyObject }, payload, header) => {
36 const { p2s, p2c } = header
37 const salt = concat(p2s)
38 const derivedKey = pbkdf2(keyObject.export(), salt, p2c, keylen, sha)
39 return unwrap({ [KEYOBJECT]: derivedKey }, payload, header)
40}
41
42module.exports = (JWA, JWK) => {
43 ['PBES2-HS256+A128KW', 'PBES2-HS384+A192KW', 'PBES2-HS512+A256KW'].forEach((jwaAlg) => {
44 const kw = jwaAlg.substr(-6)
45 const kwWrap = JWA.keyManagementEncrypt.get(kw)
46 const kwUnwrap = JWA.keyManagementDecrypt.get(kw)
47 const keylen = parseInt(jwaAlg.substr(13, 3), 10) / 8
48 const sha = `sha${jwaAlg.substr(8, 3)}`
49
50 if (kwWrap && kwUnwrap) {
51 JWA.keyManagementEncrypt.set(jwaAlg, wrapKey.bind(undefined, keylen, sha, concatSalt.bind(undefined, jwaAlg), kwWrap))
52 JWA.keyManagementDecrypt.set(jwaAlg, unwrapKey.bind(undefined, keylen, sha, concatSalt.bind(undefined, jwaAlg), kwUnwrap))
53 JWK.oct.deriveKey[jwaAlg] = key => key.use === 'enc' || key.use === undefined
54 }
55 })
56}