test-entity-library-asm 3.9.7 → 3.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -4,7 +4,7 @@ exports.JsonEncryptionTransformer = void 0;
|
|
|
4
4
|
const crypto = require("crypto");
|
|
5
5
|
const ENCRYPTION_KEY = process.env.SECRET_ENCRYPTION_KEY || "clave-32-bytes-segura";
|
|
6
6
|
const ALGORITHM = "aes-256-cbc";
|
|
7
|
-
// KeyObject de 32 bytes
|
|
7
|
+
// KeyObject de 32 bytes
|
|
8
8
|
const KEY = crypto.createSecretKey(crypto.createHash("sha256").update(String(ENCRYPTION_KEY)).digest());
|
|
9
9
|
function looksLikeCBC(encoded) {
|
|
10
10
|
// formato: iv:cipherHex
|
|
@@ -13,12 +13,10 @@ function looksLikeCBC(encoded) {
|
|
|
13
13
|
function decryptValue(value) {
|
|
14
14
|
if (typeof value !== "string" || !looksLikeCBC(value))
|
|
15
15
|
return value;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
var decipher = crypto.createDecipheriv(ALGORITHM, KEY, iv);
|
|
21
|
-
var dec = Buffer.concat([
|
|
16
|
+
const [ivHex, contentHex] = value.split(":");
|
|
17
|
+
const iv = Buffer.from(ivHex, "hex");
|
|
18
|
+
const decipher = crypto.createDecipheriv(ALGORITHM, KEY, iv);
|
|
19
|
+
const dec = Buffer.concat([
|
|
22
20
|
decipher.update(Buffer.from(contentHex, "hex")),
|
|
23
21
|
decipher.final(),
|
|
24
22
|
]);
|
|
@@ -27,45 +25,84 @@ function decryptValue(value) {
|
|
|
27
25
|
function encryptValue(plain) {
|
|
28
26
|
if (plain === null || plain === undefined)
|
|
29
27
|
return null;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
const text = String(plain);
|
|
29
|
+
const iv = crypto.randomBytes(16);
|
|
30
|
+
const cipher = crypto.createCipheriv(ALGORITHM, KEY, iv);
|
|
31
|
+
const enc = Buffer.concat([cipher.update(text, "utf8"), cipher.final()]);
|
|
34
32
|
return iv.toString("hex") + ":" + enc.toString("hex");
|
|
35
33
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
34
|
+
/** Recorre profundo y encripta solo claves `encrypted_*` */
|
|
35
|
+
function deepEncrypt(input) {
|
|
36
|
+
if (input === null || input === undefined)
|
|
37
|
+
return input;
|
|
38
|
+
if (Array.isArray(input)) {
|
|
39
|
+
const arr = [];
|
|
40
|
+
for (let i = 0; i < input.length; i++) {
|
|
41
|
+
arr[i] = deepEncrypt(input[i]);
|
|
42
|
+
}
|
|
43
|
+
return arr;
|
|
44
|
+
}
|
|
45
|
+
if (typeof input === "object") {
|
|
46
|
+
const out = {};
|
|
47
|
+
for (const k in input) {
|
|
48
|
+
const v = input[k];
|
|
44
49
|
if (k.length >= 10 && k.substr(0, 10) === "encrypted_") {
|
|
45
50
|
out[k] = encryptValue(v);
|
|
46
51
|
}
|
|
47
52
|
else {
|
|
48
|
-
out[k] = v;
|
|
53
|
+
out[k] = deepEncrypt(v);
|
|
49
54
|
}
|
|
50
55
|
}
|
|
51
|
-
return
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
// primitivos
|
|
59
|
+
return input;
|
|
60
|
+
}
|
|
61
|
+
/** Recorre profundo y desencripta solo claves `encrypted_*` */
|
|
62
|
+
function deepDecrypt(input) {
|
|
63
|
+
if (input === null || input === undefined)
|
|
64
|
+
return input;
|
|
65
|
+
if (Array.isArray(input)) {
|
|
66
|
+
const arr = [];
|
|
67
|
+
for (let i = 0; i < input.length; i++) {
|
|
68
|
+
arr[i] = deepDecrypt(input[i]);
|
|
69
|
+
}
|
|
70
|
+
return arr;
|
|
71
|
+
}
|
|
72
|
+
if (typeof input === "object") {
|
|
73
|
+
const out = {};
|
|
74
|
+
for (const k in input) {
|
|
75
|
+
const v = input[k];
|
|
76
|
+
if (k.length >= 10 && k.substr(0, 10) === "encrypted_") {
|
|
77
|
+
try {
|
|
78
|
+
out[k] = decryptValue(v);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
out[k] = v; // si está corrupto, lo dejamos como está
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
out[k] = deepDecrypt(v);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
// primitivos
|
|
91
|
+
return input;
|
|
92
|
+
}
|
|
93
|
+
exports.JsonEncryptionTransformer = {
|
|
94
|
+
to(value) {
|
|
95
|
+
if (typeof value !== "object" || value === null)
|
|
96
|
+
return JSON.stringify({});
|
|
97
|
+
return JSON.stringify(deepEncrypt(value));
|
|
52
98
|
},
|
|
53
99
|
from(dbValue) {
|
|
54
100
|
try {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (k.length >= 10 && k.substr(0, 10) === "encrypted_") {
|
|
58
|
-
try {
|
|
59
|
-
parsed[k] = decryptValue(parsed[k]);
|
|
60
|
-
}
|
|
61
|
-
catch {
|
|
62
|
-
// si falla, deja el valor original
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
return parsed;
|
|
101
|
+
const parsed = JSON.parse(dbValue);
|
|
102
|
+
return deepDecrypt(parsed);
|
|
67
103
|
}
|
|
68
104
|
catch {
|
|
105
|
+
// si no es JSON válido, no tumbar todo
|
|
69
106
|
return {};
|
|
70
107
|
}
|
|
71
108
|
},
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@ const ENCRYPTION_KEY =
|
|
|
5
5
|
process.env.SECRET_ENCRYPTION_KEY || "clave-32-bytes-segura";
|
|
6
6
|
const ALGORITHM = "aes-256-cbc";
|
|
7
7
|
|
|
8
|
-
// KeyObject de 32 bytes
|
|
8
|
+
// KeyObject de 32 bytes
|
|
9
9
|
const KEY = crypto.createSecretKey(
|
|
10
10
|
crypto.createHash("sha256").update(String(ENCRYPTION_KEY)).digest()
|
|
11
11
|
);
|
|
@@ -17,14 +17,10 @@ function looksLikeCBC(encoded: string) {
|
|
|
17
17
|
|
|
18
18
|
function decryptValue(value: any): any {
|
|
19
19
|
if (typeof value !== "string" || !looksLikeCBC(value)) return value;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
var iv = Buffer.from(ivHex, "hex");
|
|
26
|
-
var decipher = crypto.createDecipheriv(ALGORITHM, KEY, iv);
|
|
27
|
-
var dec = Buffer.concat([
|
|
20
|
+
const [ivHex, contentHex] = value.split(":");
|
|
21
|
+
const iv = Buffer.from(ivHex, "hex");
|
|
22
|
+
const decipher = crypto.createDecipheriv(ALGORITHM, KEY, iv);
|
|
23
|
+
const dec = Buffer.concat([
|
|
28
24
|
decipher.update(Buffer.from(contentHex, "hex")),
|
|
29
25
|
decipher.final(),
|
|
30
26
|
]);
|
|
@@ -33,45 +29,87 @@ function decryptValue(value: any): any {
|
|
|
33
29
|
|
|
34
30
|
function encryptValue(plain: any): string | null {
|
|
35
31
|
if (plain === null || plain === undefined) return null;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
var enc = Buffer.concat([cipher.update(text, "utf8"), cipher.final()]);
|
|
32
|
+
const text = String(plain);
|
|
33
|
+
const iv = crypto.randomBytes(16);
|
|
34
|
+
const cipher = crypto.createCipheriv(ALGORITHM, KEY, iv);
|
|
35
|
+
const enc = Buffer.concat([cipher.update(text, "utf8"), cipher.final()]);
|
|
41
36
|
return iv.toString("hex") + ":" + enc.toString("hex");
|
|
42
37
|
}
|
|
43
38
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
/** Recorre profundo y encripta solo claves `encrypted_*` */
|
|
40
|
+
function deepEncrypt(input: any): any {
|
|
41
|
+
if (input === null || input === undefined) return input;
|
|
42
|
+
|
|
43
|
+
if (Array.isArray(input)) {
|
|
44
|
+
const arr: any[] = [];
|
|
45
|
+
for (let i = 0; i < input.length; i++) {
|
|
46
|
+
arr[i] = deepEncrypt(input[i]);
|
|
47
|
+
}
|
|
48
|
+
return arr;
|
|
49
|
+
}
|
|
47
50
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
if (typeof input === "object") {
|
|
52
|
+
const out: { [k: string]: any } = {};
|
|
53
|
+
for (const k in input) {
|
|
54
|
+
const v = input[k];
|
|
52
55
|
if (k.length >= 10 && k.substr(0, 10) === "encrypted_") {
|
|
53
56
|
out[k] = encryptValue(v);
|
|
54
57
|
} else {
|
|
55
|
-
out[k] = v;
|
|
58
|
+
out[k] = deepEncrypt(v);
|
|
56
59
|
}
|
|
57
60
|
}
|
|
58
|
-
return
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// primitivos
|
|
65
|
+
return input;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Recorre profundo y desencripta solo claves `encrypted_*` */
|
|
69
|
+
function deepDecrypt(input: any): any {
|
|
70
|
+
if (input === null || input === undefined) return input;
|
|
71
|
+
|
|
72
|
+
if (Array.isArray(input)) {
|
|
73
|
+
const arr: any[] = [];
|
|
74
|
+
for (let i = 0; i < input.length; i++) {
|
|
75
|
+
arr[i] = deepDecrypt(input[i]);
|
|
76
|
+
}
|
|
77
|
+
return arr;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (typeof input === "object") {
|
|
81
|
+
const out: { [k: string]: any } = {};
|
|
82
|
+
for (const k in input) {
|
|
83
|
+
const v = input[k];
|
|
84
|
+
if (k.length >= 10 && k.substr(0, 10) === "encrypted_") {
|
|
85
|
+
try {
|
|
86
|
+
out[k] = decryptValue(v);
|
|
87
|
+
} catch {
|
|
88
|
+
out[k] = v; // si está corrupto, lo dejamos como está
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
out[k] = deepDecrypt(v);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return out;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// primitivos
|
|
98
|
+
return input;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export const JsonEncryptionTransformer: ValueTransformer = {
|
|
102
|
+
to(value: any): string {
|
|
103
|
+
if (typeof value !== "object" || value === null) return JSON.stringify({});
|
|
104
|
+
return JSON.stringify(deepEncrypt(value));
|
|
59
105
|
},
|
|
60
106
|
|
|
61
107
|
from(dbValue: string): any {
|
|
62
108
|
try {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (k.length >= 10 && k.substr(0, 10) === "encrypted_") {
|
|
66
|
-
try {
|
|
67
|
-
parsed[k] = decryptValue(parsed[k]);
|
|
68
|
-
} catch {
|
|
69
|
-
// si falla, deja el valor original
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return parsed;
|
|
109
|
+
const parsed = JSON.parse(dbValue);
|
|
110
|
+
return deepDecrypt(parsed);
|
|
74
111
|
} catch {
|
|
112
|
+
// si no es JSON válido, no tumbar todo
|
|
75
113
|
return {};
|
|
76
114
|
}
|
|
77
115
|
},
|