-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.js
119 lines (102 loc) · 3.18 KB
/
index.js
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
const crypto = require('crypto');
const alphaNumericalCheck = /^[a-zA-Z0-9]*$/;
module.exports = options => {
// Provide good defaults for the options if possible.
options = Object.assign(
{
fields: [],
algorithm: 'aes-256-cbc',
encryptionKey: '',
ivLength: 16
},
options
);
// Return the mixin.
return Model => {
return class extends Model {
async $beforeInsert(context) {
await super.$beforeInsert(context);
await this.encryptFields();
}
async $afterInsert(context) {
await super.$afterInsert(context);
return await this.decryptFields();
}
async $beforeUpdate(queryOptions, context) {
await super.$beforeUpdate(queryOptions, context);
await this.encryptFields();
}
async $afterUpdate(queryOptions, context) {
await super.$afterInsert(queryOptions, context);
return await this.decryptFields();
}
async $afterGet(context) {
await super.$afterGet(context);
return this.decryptFields();
}
/**
* Generates encryption from selected fields
*/
encryptFields() {
if (options.encryptionKey)
for (let i = 0; i < options.fields.length; i++) {
const field = options.fields[i];
const value = this[field];
if (value) {
this[field] = this.encrypt(value);
}
}
}
decryptFields() {
if (options.encryptionKey)
for (let i = 0; i < options.fields.length; i++) {
const field = options.fields[i];
const value = this[field];
if (value) {
this[field] = this.decrypt(value);
}
}
}
encrypt(text) {
if (!text) return text;
if (this.isEncrypted(text)) return text;
let iv = crypto.randomBytes(options.ivLength);
let cipher = crypto.createCipheriv(
options.algorithm,
Buffer.from(options.encryptionKey),
iv
);
let encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return iv.toString('hex') + ':' + encrypted.toString('hex');
}
decrypt(text) {
if (!text) return text;
if (!this.isEncrypted(text)) return text;
let textParts = text.split(':');
let iv = Buffer.from(textParts.shift(), 'hex');
let encryptedText = Buffer.from(textParts.join(':'), 'hex');
let decipher = crypto.createDecipheriv(
options.algorithm,
Buffer.from(options.encryptionKey),
iv
);
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}
isEncrypted(text) {
if (!text) return false;
let textParts = text.split(':');
return (
textParts.length == 2 &&
textParts[0] &&
textParts[1] &&
textParts[0].length === options.ivLength * 2 &&
alphaNumericalCheck.test(textParts[0]) &&
alphaNumericalCheck.test(textParts[1])
);
}
};
};
};