Skip to content

Commit f002f38

Browse files
authored
Merge pull request #1 from simonratner/native-aes-gcm
Use built-in cipher instead of external package
2 parents e20585c + 943c82f commit f002f38

File tree

4 files changed

+18
-30
lines changed

4 files changed

+18
-30
lines changed

lib/encrypted-attr.js

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
'use strict'
22

3+
const alg = 'aes-256-gcm'
34
const crypto = require('crypto')
4-
const gcm = require('node-aes-gcm')
55
const { get, set } = require('lodash')
66

77
function EncryptedAttributes (attributes, options) {
88
options = options || {}
99

10+
let prefix = Buffer.from(`${alg}$`).toString('base64')
11+
1012
function encryptAttribute (obj, val) {
1113
// Encrypted attributes are prefixed with "aes-256-gcm$", the base64
12-
// encoding of which is "YWVzLTI1Ni1nY20k". Nulls are not encrypted.
13-
if (val == null || (typeof val === 'string' && val.startsWith('YWVzLTI1Ni1nY20k'))) {
14+
// encoding of which is in `prefix`. Nulls are not encrypted.
15+
if (val == null || (typeof val === 'string' && val.startsWith(prefix))) {
1416
return val
1517
}
1618
if (typeof val !== 'string') {
@@ -24,11 +26,13 @@ function EncryptedAttributes (attributes, options) {
2426
let aad = Buffer.from(
2527
`aes-256-gcm$${options.verifyId ? obj.id.toString() : ''}$${options.keyId}`)
2628
let key = Buffer.from(options.keys[options.keyId], 'base64')
27-
let result = gcm.encrypt(key, iv, Buffer.from(val), aad)
29+
let gcm = crypto.createCipheriv('aes-256-gcm', key, iv).setAAD(aad)
30+
let result = gcm.update(val, 'utf8', 'base64') + gcm.final('base64')
31+
2832
return aad.toString('base64') + '$' +
2933
iv.toString('base64') + '$' +
30-
result.ciphertext.toString('base64') + '$' +
31-
result.auth_tag.toString('base64').slice(0, 22)
34+
result + '$' +
35+
gcm.getAuthTag().toString('base64').slice(0, 22)
3236
}
3337

3438
function encryptAll (obj) {
@@ -43,8 +47,8 @@ function EncryptedAttributes (attributes, options) {
4347

4448
function decryptAttribute (obj, val) {
4549
// Encrypted attributes are prefixed with "aes-256-gcm$", the base64
46-
// encoding of which is "YWVzLTI1Ni1nY20k". Nulls are not encrypted.
47-
if (typeof val !== 'string' || !val.startsWith('YWVzLTI1Ni1nY20k')) {
50+
// encoding of which is in `prefix`. Nulls are not encrypted.
51+
if (typeof val !== 'string' || !val.startsWith(prefix)) {
4852
return val
4953
}
5054
if (options.verifyId && !obj.id) {
@@ -59,11 +63,9 @@ function EncryptedAttributes (attributes, options) {
5963
throw new Error('Encrypted attribute has invalid key id')
6064
}
6165
let key = Buffer.from(options.keys[keyId], 'base64')
62-
let result = gcm.decrypt(key, iv, payload, aad, tag)
63-
if (!result.auth_ok) {
64-
throw new Error('Encrypted attribute has invalid auth tag')
65-
}
66-
return result.plaintext.toString()
66+
let gcm = crypto.createDecipheriv('aes-256-gcm', key, iv).setAAD(aad).setAuthTag(tag)
67+
68+
return gcm.update(payload, 'binary', 'utf8') + gcm.final('utf8')
6769
}
6870

6971
function decryptAll (obj) {

package-lock.json

Lines changed: 0 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
"orm"
1616
],
1717
"dependencies": {
18-
"lodash": "^4.17.4",
19-
"node-aes-gcm": "^0.2.2"
18+
"lodash": "^4.17.4"
2019
},
2120
"optionalDependencies": {},
2221
"devDependencies": {

test/encrypted-attr.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,15 +158,15 @@ describe('encrypted attributes', function () {
158158
let obj = {id: 1}
159159
// aad: aes-256-gcm$01$k2
160160
let wrongKey = 'YWVzLTI1Ni1nY20kMSRrMg==$sK91YfUvv+O8Jx/m$OOQniq8=$WLbWYz7uCQBTNO3Fc+5UvA'
161-
expect(() => enc.decryptAttribute(obj, wrongKey), 'to throw', /invalid auth tag/i)
161+
expect(() => enc.decryptAttribute(obj, wrongKey), 'to throw', /unable to auth/i)
162162
})
163163

164164
it('should throw when decrypting with wrong auth tag', function () {
165165
let enc = EncryptedAttributes(['secret'], this.options)
166166
let obj = {id: 1}
167167
// aad: aes-256-gcm$01$k1
168168
let wrongAuthTag = 'YWVzLTI1Ni1nY20kMSRrMQ==$sK91YfUvv+O8Jx/m$OOQniq8=$VLbWYz7uCQBTNO3Fc+5UvA'
169-
expect(() => enc.decryptAttribute(obj, wrongAuthTag), 'to throw', /invalid auth tag/i)
169+
expect(() => enc.decryptAttribute(obj, wrongAuthTag), 'to throw', /unable to auth/i)
170170
})
171171

172172
it('should throw when decrypting without id', function () {

0 commit comments

Comments
 (0)