1 | const { pbkdf2Sync: pbkdf2, randomBytes } = require('crypto')
|
2 |
|
3 | const { KEYOBJECT } = require('../help/consts')
|
4 | const base64url = require('../help/base64url')
|
5 |
|
6 | const SALT_LENGTH = 16
|
7 | const NULL_BUFFER = Buffer.alloc(1, 0)
|
8 |
|
9 | const concatSalt = (alg, p2s) => {
|
10 | return Buffer.concat([
|
11 | Buffer.from(alg, 'utf8'),
|
12 | NULL_BUFFER,
|
13 | p2s
|
14 | ])
|
15 | }
|
16 |
|
17 | const wrapKey = (keylen, sha, concat, wrap, { [KEYOBJECT]: keyObject }, payload) => {
|
18 |
|
19 |
|
20 |
|
21 |
|
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 |
|
35 | const 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 |
|
42 | module.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 | }
|