UNPKG

1.81 kBJavaScriptView Raw
1const { createCipheriv, createDecipheriv, getCiphers } = require('crypto')
2
3const { KEYOBJECT } = require('../help/consts')
4const { JWEInvalid, JWEDecryptionFailed } = require('../errors')
5const { asInput } = require('../help/key_object')
6
7const checkInput = function (size, iv, tag) {
8 if (iv.length !== 12) {
9 throw new JWEInvalid('invalid iv')
10 }
11 if (arguments.length === 3) {
12 if (tag.length !== 16) {
13 throw new JWEInvalid('invalid tag')
14 }
15 }
16}
17
18const encrypt = (size, { [KEYOBJECT]: keyObject }, cleartext, { iv, aad = Buffer.alloc(0) }) => {
19 const key = asInput(keyObject, false)
20 checkInput(size, iv)
21
22 const cipher = createCipheriv(`aes-${size}-gcm`, key, iv, { authTagLength: 16 })
23 cipher.setAAD(aad)
24
25 const ciphertext = Buffer.concat([cipher.update(cleartext), cipher.final()])
26 const tag = cipher.getAuthTag()
27
28 return { ciphertext, tag }
29}
30
31const decrypt = (size, { [KEYOBJECT]: keyObject }, ciphertext, { iv, tag = Buffer.alloc(0), aad = Buffer.alloc(0) }) => {
32 const key = asInput(keyObject, false)
33 checkInput(size, iv, tag)
34
35 try {
36 const cipher = createDecipheriv(`aes-${size}-gcm`, key, iv, { authTagLength: 16 })
37 cipher.setAuthTag(tag)
38 cipher.setAAD(aad)
39
40 return Buffer.concat([cipher.update(ciphertext), cipher.final()])
41 } catch (err) {
42 throw new JWEDecryptionFailed()
43 }
44}
45
46module.exports = (JWA, JWK) => {
47 ['A128GCM', 'A192GCM', 'A256GCM'].forEach((jwaAlg) => {
48 const size = parseInt(jwaAlg.substr(1, 3), 10)
49 if (getCiphers().includes(`aes-${size}-gcm`)) {
50 JWA.encrypt.set(jwaAlg, encrypt.bind(undefined, size))
51 JWA.decrypt.set(jwaAlg, decrypt.bind(undefined, size))
52 JWK.oct.encrypt[jwaAlg] = JWK.oct.decrypt[jwaAlg] = key => (key.use === 'enc' || key.use === undefined) && key.length === size
53 }
54 })
55}