1 |
|
2 |
|
3 | const crypto = require('crypto');
|
4 |
|
5 | const internal = {
|
6 | getKeyFromPassword: (password, salt, length) => crypto.pbkdf2Sync(password, salt, 100000, length, 'sha256'),
|
7 | encrypt: (text, key, algorithm, callback) => {
|
8 | crypto.randomBytes(16, (err, iv) => {
|
9 | if (err) callback(err);
|
10 | try {
|
11 | const encipher = crypto.createCipheriv(algorithm, key, iv);
|
12 | const encBuffer = Buffer.concat([iv, encipher.update(text, 'utf8'), encipher.final()]);
|
13 | callback(null, encBuffer);
|
14 | } catch (err) {
|
15 | callback(err);
|
16 | }
|
17 | });
|
18 | },
|
19 | decrypt: (enc, key, algorithm, callback) => {
|
20 | try {
|
21 | const buffer = Buffer.from(enc, 'base64');
|
22 | const iv = Buffer.from([...buffer].splice(0, 16));
|
23 | const enc2 = Buffer.from([...buffer].splice(16, buffer.length - 16));
|
24 | const decipher = crypto.createDecipheriv(algorithm, key, iv);
|
25 | const decBuffer = Buffer.concat([decipher.update(enc2), decipher.final()]);
|
26 | callback(null, decBuffer.toString('utf8'));
|
27 | } catch (err) {
|
28 | callback(err);
|
29 | }
|
30 | },
|
31 | };
|
32 |
|
33 | module.exports = (options) => {
|
34 |
|
35 | const opt = options;
|
36 | if (!opt)
|
37 | throw Error('You have to specify options for encryption module');
|
38 | else if (!opt.password && !opt.encryptionKey)
|
39 | throw Error('You have to specify password or encryption key');
|
40 | else if (opt.password && !opt.encryptionKey) {
|
41 | if(!opt.passwordSalt) {
|
42 | console.log('Warning: Default salt string used, you should specify passwordSalt option');
|
43 | opt.passwordSalt = 'PeterPan123';
|
44 | }
|
45 | opt.encryptionKey = internal.getKeyFromPassword(opt.password, opt.passwordSalt, 32);
|
46 | }
|
47 | if (opt.password)
|
48 | if (!opt.encryptionAlgorithm) { opt.encryptionAlgorithm = 'aes-256-cbc'; }
|
49 |
|
50 | return {
|
51 | options,
|
52 | encrypt: text => new Promise((resolve) => {
|
53 | internal.encrypt(text, options.encryptionKey, options.encryptionAlgorithm, (err, result) => {
|
54 | if (err) throw err;
|
55 | resolve(result.toString('base64'));
|
56 | });
|
57 | }),
|
58 | decrypt: encText => new Promise((resolve) => {
|
59 | internal.decrypt(encText,
|
60 | options.encryptionKey,
|
61 | options.encryptionAlgorithm, (err, result) => {
|
62 | if (err) throw err;
|
63 | resolve(result);
|
64 | });
|
65 | }),
|
66 | };
|
67 | };
|