-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
Copy pathencryption-internals.ts
89 lines (77 loc) · 2.14 KB
/
encryption-internals.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// @ts-strict-ignore
import crypto from 'crypto';
const ENCRYPTION_ALGORITHM = 'aes-256-gcm' as const;
export async function sha256String(str) {
return crypto.createHash('sha256').update(str).digest('base64');
}
export function randomBytes(n) {
return crypto.randomBytes(n);
}
export function encrypt(masterKey, value) {
const masterKeyBuffer = masterKey.getValue().raw;
// let iv = createKeyBuffer({ numBytes: 12, secret: masterKeyBuffer });
const iv = crypto.randomBytes(12);
const cipher = crypto.createCipheriv(
ENCRYPTION_ALGORITHM,
masterKeyBuffer,
iv,
);
let encrypted = cipher.update(value);
encrypted = Buffer.concat([encrypted, cipher.final()]);
const authTag = cipher.getAuthTag();
return {
value: encrypted,
meta: {
keyId: masterKey.getId(),
algorithm: ENCRYPTION_ALGORITHM,
iv: iv.toString('base64'),
authTag: authTag.toString('base64'),
},
};
}
export function decrypt(masterKey, encrypted, meta) {
const masterKeyBuffer = masterKey.getValue().raw;
const { algorithm, iv: originalIv, authTag: originalAuthTag } = meta;
const iv = Buffer.from(originalIv, 'base64');
const authTag = Buffer.from(originalAuthTag, 'base64');
const decipher = crypto.createDecipheriv(algorithm, masterKeyBuffer, iv);
decipher.setAuthTag(authTag);
let decrypted = decipher.update(encrypted);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted;
}
export function createKey({ secret, salt }) {
const buffer = createKeyBuffer({ secret, salt });
return {
raw: buffer,
base64: buffer.toString('base64'),
};
}
export function importKey(str) {
return {
raw: Buffer.from(str, 'base64'),
base64: str,
};
}
/**
* Generates a Buffer of a desired byte length to be used as either an encryption key or an initialization vector.
*
* @private
*/
function createKeyBuffer({
numBytes,
secret,
salt,
}: {
numBytes?: number;
secret?: string;
salt?: string;
}) {
return crypto.pbkdf2Sync(
secret || crypto.randomBytes(128).toString('base64'),
salt || crypto.randomBytes(32).toString('base64'),
10000,
numBytes || 32,
'sha512',
);
}