-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.ts
49 lines (39 loc) · 1.7 KB
/
index.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
import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';
const IV_LENGTH = 16; /** For AES, this is always 16 */
function validateInputs(text: string, secret: string) {
if ('string' !== typeof(text)) {
throw new TypeError(`Expected 'text' to be a string, but received '${text}'`);
} else if ('string' !== typeof(secret)) {
throw new TypeError(`Expected 'secret' to be a string, but received '${secret}'`);
} else if (text.length < 1) {
throw new Error(`'text' must not be an empty string`);
} else if (secret.length !== 32) {
throw new RangeError(`Invalid length of 'secret'. Must be 256 bytes or 32 characters long`);
}
}
export function encryptSync(text: string, secret: string): string {
validateInputs(text, secret);
const iv = randomBytes(IV_LENGTH);
const cipher = createCipheriv('aes-256-cbc', Buffer.from(secret), iv);
const cipherInitial = cipher.update(Buffer.from(text));
const encrypted = Buffer.concat([cipherInitial, cipher.final()]);
return `${iv.toString('hex')}:${encrypted.toString('hex')}`;
}
export function decryptSync(text: string, secret: string): string {
validateInputs(text, secret);
const [iv, encrypted] = text.split(':');
const decipher = createDecipheriv(
'aes-256-cbc',
Buffer.from(secret),
Buffer.from(iv, 'hex')
);
const decipherInitial = decipher.update(Buffer.from(encrypted, 'hex'));
const decrypted = Buffer.concat([decipherInitial, decipher.final()]);
return decrypted.toString();
}
export async function encrypt(text: string, secret: string): Promise<string> {
return encryptSync(text, secret);
}
export async function decrypt(text: string, secret: string): Promise<string> {
return decryptSync(text, secret);
}