1 | import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';
|
2 | const IV_LENGTH = 16;
|
3 | function validateInputs(text, secret) {
|
4 | if ('string' !== typeof (text)) {
|
5 | throw new TypeError(`Expected 'text' to be a string, but received '${text}'`);
|
6 | }
|
7 | else if ('string' !== typeof (secret)) {
|
8 | throw new TypeError(`Expected 'secret' to be a string, but received '${secret}'`);
|
9 | }
|
10 | else if (text.length < 1) {
|
11 | throw new Error(`'text' must not be an empty string`);
|
12 | }
|
13 | else if (secret.length !== 32) {
|
14 | throw new RangeError(`Invalid length of 'secret'. Must be 256 bytes or 32 characters long`);
|
15 | }
|
16 | }
|
17 | export function encryptSync(text, secret) {
|
18 | validateInputs(text, secret);
|
19 | const iv = randomBytes(IV_LENGTH);
|
20 | const cipher = createCipheriv('aes-256-cbc', Buffer.from(secret), iv);
|
21 | const cipherInitial = cipher.update(Buffer.from(text));
|
22 | const encrypted = Buffer.concat([cipherInitial, cipher.final()]);
|
23 | return `${iv.toString('hex')}:${encrypted.toString('hex')}`;
|
24 | }
|
25 | export function decryptSync(text, secret) {
|
26 | validateInputs(text, secret);
|
27 | const [iv, encrypted] = text.split(':');
|
28 | const decipher = createDecipheriv('aes-256-cbc', Buffer.from(secret), Buffer.from(iv, 'hex'));
|
29 | const decipherInitial = decipher.update(Buffer.from(encrypted, 'hex'));
|
30 | const decrypted = Buffer.concat([decipherInitial, decipher.final()]);
|
31 | return decrypted.toString();
|
32 | }
|
33 | export async function encrypt(text, secret) {
|
34 | return encryptSync(text, secret);
|
35 | }
|
36 | export async function decrypt(text, secret) {
|
37 | return decryptSync(text, secret);
|
38 | }
|
39 |
|
\ | No newline at end of file |