@futdevpro/fsm-dynamo 1.10.49 → 1.10.51
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.
- package/build/_modules/crypto/_collections/crypto-non-stable.util.d.ts +80 -0
- package/build/_modules/crypto/_collections/crypto-non-stable.util.d.ts.map +1 -0
- package/build/_modules/crypto/_collections/crypto-non-stable.util.js +229 -0
- package/build/_modules/crypto/_collections/crypto-non-stable.util.js.map +1 -0
- package/build/_modules/crypto/_collections/crypto.util.d.ts +13 -45
- package/build/_modules/crypto/_collections/crypto.util.d.ts.map +1 -1
- package/build/_modules/crypto/_collections/crypto.util.js +71 -96
- package/build/_modules/crypto/_collections/crypto.util.js.map +1 -1
- package/build/_modules/crypto/_collections/crypto.util.spec.js +6 -4
- package/build/_modules/crypto/_collections/crypto.util.spec.js.map +1 -1
- package/build/_modules/pipe/_collections/pip-transforms.const.d.ts +5 -0
- package/build/_modules/pipe/_collections/pip-transforms.const.d.ts.map +1 -1
- package/build/_modules/pipe/_collections/pip-transforms.const.js +5 -0
- package/build/_modules/pipe/_collections/pip-transforms.const.js.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-country-pipe.util.d.ts +24 -0
- package/build/_modules/pipe/_collections/utils/pip-country-pipe.util.d.ts.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-country-pipe.util.js +24 -0
- package/build/_modules/pipe/_collections/utils/pip-country-pipe.util.js.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-custom-pipe.util.d.ts +20 -1
- package/build/_modules/pipe/_collections/utils/pip-custom-pipe.util.d.ts.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-custom-pipe.util.js +21 -2
- package/build/_modules/pipe/_collections/utils/pip-custom-pipe.util.js.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-division-pipe.util.d.ts +16 -0
- package/build/_modules/pipe/_collections/utils/pip-division-pipe.util.d.ts.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-division-pipe.util.js +16 -0
- package/build/_modules/pipe/_collections/utils/pip-division-pipe.util.js.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-list-pipe.util.d.ts +16 -0
- package/build/_modules/pipe/_collections/utils/pip-list-pipe.util.d.ts.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-list-pipe.util.js +16 -0
- package/build/_modules/pipe/_collections/utils/pip-list-pipe.util.js.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-multi-pipe-pipe.util.d.ts +53 -0
- package/build/_modules/pipe/_collections/utils/pip-multi-pipe-pipe.util.d.ts.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-multi-pipe-pipe.util.js +53 -0
- package/build/_modules/pipe/_collections/utils/pip-multi-pipe-pipe.util.js.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-obj-key-pipe.util.d.ts +13 -0
- package/build/_modules/pipe/_collections/utils/pip-obj-key-pipe.util.d.ts.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-obj-key-pipe.util.js +13 -0
- package/build/_modules/pipe/_collections/utils/pip-obj-key-pipe.util.js.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-range-pipe.util.d.ts +12 -0
- package/build/_modules/pipe/_collections/utils/pip-range-pipe.util.d.ts.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-range-pipe.util.js +12 -0
- package/build/_modules/pipe/_collections/utils/pip-range-pipe.util.js.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-region-pipe.util.d.ts +17 -0
- package/build/_modules/pipe/_collections/utils/pip-region-pipe.util.d.ts.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-region-pipe.util.js +17 -0
- package/build/_modules/pipe/_collections/utils/pip-region-pipe.util.js.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-replace-pipe.util.d.ts +12 -0
- package/build/_modules/pipe/_collections/utils/pip-replace-pipe.util.d.ts.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-replace-pipe.util.js +12 -0
- package/build/_modules/pipe/_collections/utils/pip-replace-pipe.util.js.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-slider-pipe.util.d.ts +14 -0
- package/build/_modules/pipe/_collections/utils/pip-slider-pipe.util.d.ts.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-slider-pipe.util.js +14 -0
- package/build/_modules/pipe/_collections/utils/pip-slider-pipe.util.js.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-smart-replace-pipe.util.d.ts +9 -1
- package/build/_modules/pipe/_collections/utils/pip-smart-replace-pipe.util.d.ts.map +1 -1
- package/build/_modules/pipe/_collections/utils/pip-smart-replace-pipe.util.js +9 -1
- package/build/_modules/pipe/_collections/utils/pip-smart-replace-pipe.util.js.map +1 -1
- package/futdevpro-fsm-dynamo-01.10.51.tgz +0 -0
- package/package.json +1 -1
- package/src/_modules/crypto/_collections/crypto-non-stable.util.ts +285 -0
- package/src/_modules/crypto/_collections/crypto.util.spec.ts +6 -4
- package/src/_modules/crypto/_collections/crypto.util.ts +82 -143
- package/src/_modules/pipe/_collections/pip-transforms.const.ts +5 -1
- package/src/_modules/pipe/_collections/utils/pip-country-pipe.util.ts +24 -1
- package/src/_modules/pipe/_collections/utils/pip-custom-pipe.util.ts +24 -3
- package/src/_modules/pipe/_collections/utils/pip-division-pipe.util.ts +16 -0
- package/src/_modules/pipe/_collections/utils/pip-list-pipe.util.ts +16 -1
- package/src/_modules/pipe/_collections/utils/pip-multi-pipe-pipe.util.ts +53 -0
- package/src/_modules/pipe/_collections/utils/pip-obj-key-pipe.util.ts +13 -1
- package/src/_modules/pipe/_collections/utils/pip-range-pipe.util.ts +12 -0
- package/src/_modules/pipe/_collections/utils/pip-region-pipe.util.ts +17 -0
- package/src/_modules/pipe/_collections/utils/pip-replace-pipe.util.ts +12 -0
- package/src/_modules/pipe/_collections/utils/pip-slider-pipe.util.ts +14 -0
- package/src/_modules/pipe/_collections/utils/pip-smart-replace-pipe.util.ts +9 -1
- package/futdevpro-fsm-dynamo-01.10.49.tgz +0 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error codes for crypto operations
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Configuration options for encryption/decryption
|
|
6
|
+
*/
|
|
7
|
+
export interface CryptoConfig {
|
|
8
|
+
ivLength?: number;
|
|
9
|
+
saltLength?: number;
|
|
10
|
+
keyIterations?: number;
|
|
11
|
+
keySize?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A utility class for secure encryption and decryption of data
|
|
15
|
+
* Uses AES-256-CBC with PBKDF2 key derivation
|
|
16
|
+
*/
|
|
17
|
+
export declare class DyFM_Crypto {
|
|
18
|
+
private static readonly DEFAULT_CONFIG;
|
|
19
|
+
private static readonly defaultErrorUserMsg;
|
|
20
|
+
/**
|
|
21
|
+
* Validates the input data and key
|
|
22
|
+
* @throws {DyFM_Error} if validation fails
|
|
23
|
+
*/
|
|
24
|
+
private static validateInput;
|
|
25
|
+
/**
|
|
26
|
+
* Generates a deterministic IV based on the input data and key
|
|
27
|
+
*/
|
|
28
|
+
private static generateIV;
|
|
29
|
+
/**
|
|
30
|
+
* Generates a deterministic salt based on the input data and key
|
|
31
|
+
*/
|
|
32
|
+
private static generateSalt;
|
|
33
|
+
/**
|
|
34
|
+
* Derives a key using PBKDF2
|
|
35
|
+
*/
|
|
36
|
+
private static deriveKey;
|
|
37
|
+
/**
|
|
38
|
+
* Safely serializes data to JSON
|
|
39
|
+
*/
|
|
40
|
+
private static safeSerialize;
|
|
41
|
+
/**
|
|
42
|
+
* Safely deserializes JSON data
|
|
43
|
+
*/
|
|
44
|
+
private static safeDeserialize;
|
|
45
|
+
/**
|
|
46
|
+
* Encrypts data using AES-256-CBC
|
|
47
|
+
* @param data The data to encrypt
|
|
48
|
+
* @param key The encryption key
|
|
49
|
+
* @param config Optional configuration
|
|
50
|
+
* @returns URL-safe encrypted string
|
|
51
|
+
* @throws {DyFM_Error} if encryption fails
|
|
52
|
+
*/
|
|
53
|
+
static encrypt<T>(data: T, key: string, config?: CryptoConfig): string;
|
|
54
|
+
/**
|
|
55
|
+
* Decrypts data that was encrypted using encrypt()
|
|
56
|
+
* @param encryptedData The encrypted data
|
|
57
|
+
* @param key The decryption key
|
|
58
|
+
* @param config Optional configuration
|
|
59
|
+
* @returns The decrypted data
|
|
60
|
+
* @throws {DyFM_Error} if decryption fails
|
|
61
|
+
*/
|
|
62
|
+
static decrypt<T>(encryptedData: string, key: string, config?: CryptoConfig): T;
|
|
63
|
+
/**
|
|
64
|
+
* Generates a secure random key
|
|
65
|
+
* @param length Length of the key in bytes (default: 32)
|
|
66
|
+
* @returns A secure random key
|
|
67
|
+
*/
|
|
68
|
+
static generateKey(length?: number): string;
|
|
69
|
+
/**
|
|
70
|
+
* Validates if a string is a valid encrypted data
|
|
71
|
+
* @param encryptedData The data to validate
|
|
72
|
+
* @returns true if the data appears to be valid encrypted data
|
|
73
|
+
*/
|
|
74
|
+
static isValidEncryptedData(encryptedData: string): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Gets default error settings
|
|
77
|
+
*/
|
|
78
|
+
private static getDefaultErrorSettings;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=crypto-non-stable.util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto-non-stable.util.d.ts","sourceRoot":"","sources":["../../../../src/_modules/crypto/_collections/crypto-non-stable.util.ts"],"names":[],"mappings":"AAOA;;GAEG;AASH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAKpC;IACF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAEY;IAMvD;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAkB5B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU;IAKzB;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;IAK3B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS;IAOxB;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAY5B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;IA6B9B;;;;;;;OAOG;IACH,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM;IAsCtE;;;;;;;OAOG;IACH,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,CAAC;IAwD/E;;;;OAIG;IACH,MAAM,CAAC,WAAW,CAAC,MAAM,GAAE,MAAW,GAAG,MAAM;IAI/C;;;;OAIG;IACH,MAAM,CAAC,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO;IAO3D;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,uBAAuB;CAQvC"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DyFM_Crypto = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const CryptoJS = tslib_1.__importStar(require("crypto-js"));
|
|
6
|
+
const error_control_model_1 = require("../../../_models/control-models/error.control-model");
|
|
7
|
+
/**
|
|
8
|
+
* A utility class for secure encryption and decryption of data
|
|
9
|
+
* Uses AES-256-CBC with PBKDF2 key derivation
|
|
10
|
+
*/
|
|
11
|
+
class DyFM_Crypto {
|
|
12
|
+
static DEFAULT_CONFIG = {
|
|
13
|
+
ivLength: 16, // 128 bits
|
|
14
|
+
saltLength: 16, // 128 bits
|
|
15
|
+
keyIterations: 10000,
|
|
16
|
+
keySize: 8 // 256 bits (8 * 32)
|
|
17
|
+
};
|
|
18
|
+
static defaultErrorUserMsg = `We encountered an unhandled Authentication Error, ` +
|
|
19
|
+
`\nplease contact the responsible development team.`;
|
|
20
|
+
// Tömör: kb. 60–80 karakteres token, nem 200+
|
|
21
|
+
// Nem szabványos: nehéz visszafejteni
|
|
22
|
+
// Használható cookie, header, URL-ben
|
|
23
|
+
/**
|
|
24
|
+
* Validates the input data and key
|
|
25
|
+
* @throws {DyFM_Error} if validation fails
|
|
26
|
+
*/
|
|
27
|
+
static validateInput(data, key) {
|
|
28
|
+
if (!key || typeof key !== 'string' || key.trim().length === 0) {
|
|
29
|
+
throw new error_control_model_1.DyFM_Error({
|
|
30
|
+
...this.getDefaultErrorSettings('validateInput'),
|
|
31
|
+
errorCode: 'DyFM-CRY-IKY',
|
|
32
|
+
message: 'Invalid encryption key'
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
if (data === undefined || data === null) {
|
|
36
|
+
throw new error_control_model_1.DyFM_Error({
|
|
37
|
+
...this.getDefaultErrorSettings('validateInput'),
|
|
38
|
+
errorCode: 'DyFM-CRY-IDT',
|
|
39
|
+
message: 'Invalid data to encrypt/decrypt'
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Generates a deterministic IV based on the input data and key
|
|
45
|
+
*/
|
|
46
|
+
static generateIV(data, key, config) {
|
|
47
|
+
const hash = CryptoJS.SHA256(data + key);
|
|
48
|
+
return CryptoJS.lib.WordArray.create(hash.words.slice(0, config.ivLength / 4));
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Generates a deterministic salt based on the input data and key
|
|
52
|
+
*/
|
|
53
|
+
static generateSalt(data, key, config) {
|
|
54
|
+
const hash = CryptoJS.SHA256(key + data);
|
|
55
|
+
return CryptoJS.lib.WordArray.create(hash.words.slice(0, config.saltLength / 4));
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Derives a key using PBKDF2
|
|
59
|
+
*/
|
|
60
|
+
static deriveKey(key, salt, config) {
|
|
61
|
+
return CryptoJS.PBKDF2(key, salt, {
|
|
62
|
+
keySize: config.keySize,
|
|
63
|
+
iterations: config.keyIterations
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Safely serializes data to JSON
|
|
68
|
+
*/
|
|
69
|
+
static safeSerialize(data) {
|
|
70
|
+
try {
|
|
71
|
+
return JSON.stringify(data);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
throw new error_control_model_1.DyFM_Error({
|
|
75
|
+
...this.getDefaultErrorSettings('safeSerialize', error),
|
|
76
|
+
errorCode: 'DyFM-CRY-SER',
|
|
77
|
+
message: 'Failed to serialize data'
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Safely deserializes JSON data
|
|
83
|
+
*/
|
|
84
|
+
static safeDeserialize(data) {
|
|
85
|
+
try {
|
|
86
|
+
let parsed = JSON.parse(data);
|
|
87
|
+
// Handle double-stringified JSON
|
|
88
|
+
if (typeof parsed === 'string') {
|
|
89
|
+
try {
|
|
90
|
+
parsed = JSON.parse(parsed);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// If second parse fails, return the string as is
|
|
94
|
+
return parsed;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Handle primitive values
|
|
98
|
+
if (typeof parsed === 'string' || typeof parsed === 'number' || typeof parsed === 'boolean') {
|
|
99
|
+
return parsed;
|
|
100
|
+
}
|
|
101
|
+
return parsed;
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
throw new error_control_model_1.DyFM_Error({
|
|
105
|
+
...this.getDefaultErrorSettings('safeDeserialize', error),
|
|
106
|
+
errorCode: 'DyFM-CRY-DES',
|
|
107
|
+
message: 'Failed to deserialize data'
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Encrypts data using AES-256-CBC
|
|
113
|
+
* @param data The data to encrypt
|
|
114
|
+
* @param key The encryption key
|
|
115
|
+
* @param config Optional configuration
|
|
116
|
+
* @returns URL-safe encrypted string
|
|
117
|
+
* @throws {DyFM_Error} if encryption fails
|
|
118
|
+
*/
|
|
119
|
+
static encrypt(data, key, config) {
|
|
120
|
+
try {
|
|
121
|
+
this.validateInput(data, key);
|
|
122
|
+
const finalConfig = { ...this.DEFAULT_CONFIG, ...config };
|
|
123
|
+
// Convert data to string
|
|
124
|
+
const dataStr = this.safeSerialize(data);
|
|
125
|
+
// Generate deterministic IV and salt based on data and key
|
|
126
|
+
const iv = this.generateIV(dataStr, key, finalConfig);
|
|
127
|
+
const salt = this.generateSalt(dataStr, key, finalConfig);
|
|
128
|
+
// Derive key using PBKDF2
|
|
129
|
+
const derivedKey = this.deriveKey(key, salt, finalConfig);
|
|
130
|
+
// Encrypt the data
|
|
131
|
+
const encrypted = CryptoJS.AES.encrypt(dataStr, derivedKey, {
|
|
132
|
+
iv: iv,
|
|
133
|
+
mode: CryptoJS.mode.CBC,
|
|
134
|
+
padding: CryptoJS.pad.Pkcs7
|
|
135
|
+
});
|
|
136
|
+
// Combine IV + Salt + Ciphertext
|
|
137
|
+
const combined = iv.concat(salt).concat(encrypted.ciphertext);
|
|
138
|
+
// Convert to URL-safe base64
|
|
139
|
+
return CryptoJS.enc.Base64.stringify(combined)
|
|
140
|
+
.replace(/\+/g, '-')
|
|
141
|
+
.replace(/\//g, '_')
|
|
142
|
+
.replace(/=+$/, '');
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
throw new error_control_model_1.DyFM_Error({
|
|
146
|
+
...this.getDefaultErrorSettings('encrypt', error),
|
|
147
|
+
errorCode: 'DyFM-CRY-ENC',
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Decrypts data that was encrypted using encrypt()
|
|
153
|
+
* @param encryptedData The encrypted data
|
|
154
|
+
* @param key The decryption key
|
|
155
|
+
* @param config Optional configuration
|
|
156
|
+
* @returns The decrypted data
|
|
157
|
+
* @throws {DyFM_Error} if decryption fails
|
|
158
|
+
*/
|
|
159
|
+
static decrypt(encryptedData, key, config) {
|
|
160
|
+
try {
|
|
161
|
+
this.validateInput(encryptedData, key);
|
|
162
|
+
const finalConfig = { ...this.DEFAULT_CONFIG, ...config };
|
|
163
|
+
// Convert from URL-safe base64
|
|
164
|
+
const base64 = encryptedData
|
|
165
|
+
.replace(/-/g, '+')
|
|
166
|
+
.replace(/_/g, '/');
|
|
167
|
+
// Parse the combined data
|
|
168
|
+
const combined = CryptoJS.enc.Base64.parse(base64);
|
|
169
|
+
// Validate minimum length (IV + Salt + minimum ciphertext)
|
|
170
|
+
const minLength = (finalConfig.ivLength + finalConfig.saltLength + 16) / 4; // 16 bytes minimum for ciphertext
|
|
171
|
+
if (combined.words.length < minLength) {
|
|
172
|
+
throw new Error('Invalid encrypted data length');
|
|
173
|
+
}
|
|
174
|
+
// Extract IV, salt, and ciphertext
|
|
175
|
+
const iv = CryptoJS.lib.WordArray.create(combined.words.slice(0, finalConfig.ivLength / 4));
|
|
176
|
+
const salt = CryptoJS.lib.WordArray.create(combined.words.slice(finalConfig.ivLength / 4, (finalConfig.ivLength + finalConfig.saltLength) / 4));
|
|
177
|
+
const ciphertext = CryptoJS.lib.WordArray.create(combined.words.slice((finalConfig.ivLength + finalConfig.saltLength) / 4));
|
|
178
|
+
// Derive key using PBKDF2
|
|
179
|
+
const derivedKey = this.deriveKey(key, salt, finalConfig);
|
|
180
|
+
// Decrypt the data
|
|
181
|
+
const decrypted = CryptoJS.AES.decrypt({ ciphertext: ciphertext }, derivedKey, {
|
|
182
|
+
iv: iv,
|
|
183
|
+
mode: CryptoJS.mode.CBC,
|
|
184
|
+
padding: CryptoJS.pad.Pkcs7
|
|
185
|
+
});
|
|
186
|
+
// Parse JSON
|
|
187
|
+
const decryptedStr = decrypted.toString(CryptoJS.enc.Utf8);
|
|
188
|
+
return this.safeDeserialize(decryptedStr);
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
throw new error_control_model_1.DyFM_Error({
|
|
192
|
+
...this.getDefaultErrorSettings('decrypt', error),
|
|
193
|
+
errorCode: 'DyFM-CRY-DRY',
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Generates a secure random key
|
|
199
|
+
* @param length Length of the key in bytes (default: 32)
|
|
200
|
+
* @returns A secure random key
|
|
201
|
+
*/
|
|
202
|
+
static generateKey(length = 32) {
|
|
203
|
+
return CryptoJS.lib.WordArray.random(length).toString();
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Validates if a string is a valid encrypted data
|
|
207
|
+
* @param encryptedData The data to validate
|
|
208
|
+
* @returns true if the data appears to be valid encrypted data
|
|
209
|
+
*/
|
|
210
|
+
static isValidEncryptedData(encryptedData) {
|
|
211
|
+
if (!encryptedData || typeof encryptedData !== 'string') {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
return /^[A-Za-z0-9\-_]+$/.test(encryptedData);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Gets default error settings
|
|
218
|
+
*/
|
|
219
|
+
static getDefaultErrorSettings(operation, error) {
|
|
220
|
+
return {
|
|
221
|
+
status: error?.___status ?? error?.status ?? 401,
|
|
222
|
+
message: `Crypto operation "${operation}" failed`,
|
|
223
|
+
error: error,
|
|
224
|
+
errorCode: 'DyFM-CRY-ERR'
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
exports.DyFM_Crypto = DyFM_Crypto;
|
|
229
|
+
//# sourceMappingURL=crypto-non-stable.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto-non-stable.util.js","sourceRoot":"","sources":["../../../../src/_modules/crypto/_collections/crypto-non-stable.util.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,77 +1,45 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Error codes for crypto operations
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Configuration options for encryption/decryption
|
|
6
|
-
*/
|
|
7
|
-
export interface CryptoConfig {
|
|
8
|
-
ivLength?: number;
|
|
9
|
-
saltLength?: number;
|
|
10
|
-
keyIterations?: number;
|
|
11
|
-
keySize?: number;
|
|
12
|
-
}
|
|
13
1
|
/**
|
|
14
2
|
* A utility class for secure encryption and decryption of data
|
|
15
|
-
* Uses AES-256-CBC with
|
|
3
|
+
* Uses AES-256-CBC with deterministic IV and salt for consistent results
|
|
16
4
|
*/
|
|
17
5
|
export declare class DyFM_Crypto {
|
|
18
|
-
private static readonly DEFAULT_CONFIG;
|
|
19
6
|
private static readonly defaultErrorUserMsg;
|
|
20
7
|
/**
|
|
21
|
-
* Validates the
|
|
22
|
-
* @throws {DyFM_Error} if validation fails
|
|
8
|
+
* Validates the encryption key
|
|
23
9
|
*/
|
|
24
|
-
private static
|
|
10
|
+
private static validateKey;
|
|
25
11
|
/**
|
|
26
|
-
*
|
|
12
|
+
* Safely serializes data to JSON
|
|
27
13
|
*/
|
|
28
|
-
private static
|
|
14
|
+
private static safeSerialize;
|
|
29
15
|
/**
|
|
30
|
-
*
|
|
16
|
+
* Safely deserializes JSON data
|
|
31
17
|
*/
|
|
32
|
-
private static
|
|
18
|
+
private static safeDeserialize;
|
|
33
19
|
/**
|
|
34
|
-
* Derives a key using
|
|
20
|
+
* Derives a 256-bit key from the passphrase using SHA256
|
|
35
21
|
*/
|
|
36
22
|
private static deriveKey;
|
|
37
23
|
/**
|
|
38
|
-
*
|
|
24
|
+
* Creates a deterministic IV from the key only
|
|
39
25
|
*/
|
|
40
|
-
private static
|
|
41
|
-
/**
|
|
42
|
-
* Safely deserializes JSON data
|
|
43
|
-
*/
|
|
44
|
-
private static safeDeserialize;
|
|
26
|
+
private static createDeterministicIV;
|
|
45
27
|
/**
|
|
46
|
-
* Encrypts data using AES-256-CBC
|
|
28
|
+
* Encrypts data using AES-256-CBC with deterministic key and IV
|
|
47
29
|
* @param data The data to encrypt
|
|
48
30
|
* @param key The encryption key
|
|
49
|
-
* @param config Optional configuration
|
|
50
31
|
* @returns URL-safe encrypted string
|
|
51
32
|
* @throws {DyFM_Error} if encryption fails
|
|
52
33
|
*/
|
|
53
|
-
static encrypt<T>(data: T, key: string
|
|
34
|
+
static encrypt<T>(data: T, key: string): string;
|
|
54
35
|
/**
|
|
55
36
|
* Decrypts data that was encrypted using encrypt()
|
|
56
37
|
* @param encryptedData The encrypted data
|
|
57
38
|
* @param key The decryption key
|
|
58
|
-
* @param config Optional configuration
|
|
59
39
|
* @returns The decrypted data
|
|
60
40
|
* @throws {DyFM_Error} if decryption fails
|
|
61
41
|
*/
|
|
62
|
-
static decrypt<T>(encryptedData: string, key: string
|
|
63
|
-
/**
|
|
64
|
-
* Generates a secure random key
|
|
65
|
-
* @param length Length of the key in bytes (default: 32)
|
|
66
|
-
* @returns A secure random key
|
|
67
|
-
*/
|
|
68
|
-
static generateKey(length?: number): string;
|
|
69
|
-
/**
|
|
70
|
-
* Validates if a string is a valid encrypted data
|
|
71
|
-
* @param encryptedData The data to validate
|
|
72
|
-
* @returns true if the data appears to be valid encrypted data
|
|
73
|
-
*/
|
|
74
|
-
static isValidEncryptedData(encryptedData: string): boolean;
|
|
42
|
+
static decrypt<T>(encryptedData: string, key: string): T;
|
|
75
43
|
/**
|
|
76
44
|
* Gets default error settings
|
|
77
45
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypto.util.d.ts","sourceRoot":"","sources":["../../../../src/_modules/crypto/_collections/crypto.util.ts"],"names":[],"mappings":"AAOA
|
|
1
|
+
{"version":3,"file":"crypto.util.d.ts","sourceRoot":"","sources":["../../../../src/_modules/crypto/_collections/crypto.util.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAEY;IAEvD;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAkB1B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAY5B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;IA6B9B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS;IAIxB;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAKpC;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;IA0C/C;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC;IAyDxD;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,uBAAuB;CAQvC"}
|
|
@@ -6,63 +6,30 @@ const CryptoJS = tslib_1.__importStar(require("crypto-js"));
|
|
|
6
6
|
const error_control_model_1 = require("../../../_models/control-models/error.control-model");
|
|
7
7
|
/**
|
|
8
8
|
* A utility class for secure encryption and decryption of data
|
|
9
|
-
* Uses AES-256-CBC with
|
|
9
|
+
* Uses AES-256-CBC with deterministic IV and salt for consistent results
|
|
10
10
|
*/
|
|
11
11
|
class DyFM_Crypto {
|
|
12
|
-
static DEFAULT_CONFIG = {
|
|
13
|
-
ivLength: 16, // 128 bits
|
|
14
|
-
saltLength: 16, // 128 bits
|
|
15
|
-
keyIterations: 10000,
|
|
16
|
-
keySize: 8 // 256 bits (8 * 32)
|
|
17
|
-
};
|
|
18
12
|
static defaultErrorUserMsg = `We encountered an unhandled Authentication Error, ` +
|
|
19
13
|
`\nplease contact the responsible development team.`;
|
|
20
|
-
// Tömör: kb. 60–80 karakteres token, nem 200+
|
|
21
|
-
// Nem szabványos: nehéz visszafejteni
|
|
22
|
-
// Használható cookie, header, URL-ben
|
|
23
14
|
/**
|
|
24
|
-
* Validates the
|
|
25
|
-
* @throws {DyFM_Error} if validation fails
|
|
15
|
+
* Validates the encryption key
|
|
26
16
|
*/
|
|
27
|
-
static
|
|
28
|
-
if (!key || typeof key !== 'string'
|
|
17
|
+
static validateKey(key) {
|
|
18
|
+
if (!key || typeof key !== 'string') {
|
|
29
19
|
throw new error_control_model_1.DyFM_Error({
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
20
|
+
status: 401,
|
|
21
|
+
message: 'Encryption key is required and must be a string',
|
|
22
|
+
errorCode: 'DyFM-CRY-KEY-REQ'
|
|
33
23
|
});
|
|
34
24
|
}
|
|
35
|
-
if (
|
|
25
|
+
if (key.trim().length === 0) {
|
|
36
26
|
throw new error_control_model_1.DyFM_Error({
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
27
|
+
status: 401,
|
|
28
|
+
message: 'Encryption key cannot be empty or whitespace-only',
|
|
29
|
+
errorCode: 'DyFM-CRY-KEY-EMPTY'
|
|
40
30
|
});
|
|
41
31
|
}
|
|
42
32
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Generates a deterministic IV based on the input data and key
|
|
45
|
-
*/
|
|
46
|
-
static generateIV(data, key, config) {
|
|
47
|
-
const hash = CryptoJS.SHA256(data + key);
|
|
48
|
-
return CryptoJS.lib.WordArray.create(hash.words.slice(0, config.ivLength / 4));
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Generates a deterministic salt based on the input data and key
|
|
52
|
-
*/
|
|
53
|
-
static generateSalt(data, key, config) {
|
|
54
|
-
const hash = CryptoJS.SHA256(key + data);
|
|
55
|
-
return CryptoJS.lib.WordArray.create(hash.words.slice(0, config.saltLength / 4));
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Derives a key using PBKDF2
|
|
59
|
-
*/
|
|
60
|
-
static deriveKey(key, salt, config) {
|
|
61
|
-
return CryptoJS.PBKDF2(key, salt, {
|
|
62
|
-
keySize: config.keySize,
|
|
63
|
-
iterations: config.keyIterations
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
33
|
/**
|
|
67
34
|
* Safely serializes data to JSON
|
|
68
35
|
*/
|
|
@@ -109,34 +76,51 @@ class DyFM_Crypto {
|
|
|
109
76
|
}
|
|
110
77
|
}
|
|
111
78
|
/**
|
|
112
|
-
*
|
|
79
|
+
* Derives a 256-bit key from the passphrase using SHA256
|
|
80
|
+
*/
|
|
81
|
+
static deriveKey(key) {
|
|
82
|
+
return CryptoJS.SHA256(key);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Creates a deterministic IV from the key only
|
|
86
|
+
*/
|
|
87
|
+
static createDeterministicIV(key) {
|
|
88
|
+
const hash = CryptoJS.SHA256(key + ':iv');
|
|
89
|
+
return CryptoJS.lib.WordArray.create(hash.words.slice(0, 4)); // Use first 16 bytes (128 bits)
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Encrypts data using AES-256-CBC with deterministic key and IV
|
|
113
93
|
* @param data The data to encrypt
|
|
114
94
|
* @param key The encryption key
|
|
115
|
-
* @param config Optional configuration
|
|
116
95
|
* @returns URL-safe encrypted string
|
|
117
96
|
* @throws {DyFM_Error} if encryption fails
|
|
118
97
|
*/
|
|
119
|
-
static encrypt(data, key
|
|
98
|
+
static encrypt(data, key) {
|
|
120
99
|
try {
|
|
121
|
-
|
|
122
|
-
|
|
100
|
+
// Validate key
|
|
101
|
+
this.validateKey(key);
|
|
102
|
+
// Validate data
|
|
103
|
+
if (data === undefined || data === null) {
|
|
104
|
+
throw new error_control_model_1.DyFM_Error({
|
|
105
|
+
status: 401,
|
|
106
|
+
message: 'Data cannot be undefined or null',
|
|
107
|
+
errorCode: 'DyFM-CRY-DATA-NULL'
|
|
108
|
+
});
|
|
109
|
+
}
|
|
123
110
|
// Convert data to string
|
|
124
111
|
const dataStr = this.safeSerialize(data);
|
|
125
|
-
//
|
|
126
|
-
const
|
|
127
|
-
const
|
|
128
|
-
//
|
|
129
|
-
const
|
|
130
|
-
// Encrypt the data
|
|
131
|
-
const encrypted = CryptoJS.AES.encrypt(dataStr, derivedKey, {
|
|
112
|
+
// Derive key and IV
|
|
113
|
+
const aesKey = this.deriveKey(key);
|
|
114
|
+
const iv = this.createDeterministicIV(key);
|
|
115
|
+
// Encrypt the data with deterministic key and IV
|
|
116
|
+
const encrypted = CryptoJS.AES.encrypt(dataStr, aesKey, {
|
|
132
117
|
iv: iv,
|
|
133
118
|
mode: CryptoJS.mode.CBC,
|
|
134
119
|
padding: CryptoJS.pad.Pkcs7
|
|
135
120
|
});
|
|
136
|
-
// Combine IV + Salt + Ciphertext
|
|
137
|
-
const combined = iv.concat(salt).concat(encrypted.ciphertext);
|
|
138
121
|
// Convert to URL-safe base64
|
|
139
|
-
|
|
122
|
+
const base64 = encrypted.ciphertext.toString(CryptoJS.enc.Base64);
|
|
123
|
+
return base64
|
|
140
124
|
.replace(/\+/g, '-')
|
|
141
125
|
.replace(/\//g, '_')
|
|
142
126
|
.replace(/=+$/, '');
|
|
@@ -152,39 +136,49 @@ class DyFM_Crypto {
|
|
|
152
136
|
* Decrypts data that was encrypted using encrypt()
|
|
153
137
|
* @param encryptedData The encrypted data
|
|
154
138
|
* @param key The decryption key
|
|
155
|
-
* @param config Optional configuration
|
|
156
139
|
* @returns The decrypted data
|
|
157
140
|
* @throws {DyFM_Error} if decryption fails
|
|
158
141
|
*/
|
|
159
|
-
static decrypt(encryptedData, key
|
|
142
|
+
static decrypt(encryptedData, key) {
|
|
160
143
|
try {
|
|
161
|
-
|
|
162
|
-
|
|
144
|
+
// Validate key
|
|
145
|
+
this.validateKey(key);
|
|
146
|
+
// Validate encrypted data
|
|
147
|
+
if (!encryptedData || typeof encryptedData !== 'string') {
|
|
148
|
+
throw new error_control_model_1.DyFM_Error({
|
|
149
|
+
status: 401,
|
|
150
|
+
message: 'Encrypted data is required and must be a string',
|
|
151
|
+
errorCode: 'DyFM-CRY-DATA-REQ'
|
|
152
|
+
});
|
|
153
|
+
}
|
|
163
154
|
// Convert from URL-safe base64
|
|
164
|
-
|
|
155
|
+
let base64 = encryptedData
|
|
165
156
|
.replace(/-/g, '+')
|
|
166
157
|
.replace(/_/g, '/');
|
|
167
|
-
//
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if (combined.words.length < minLength) {
|
|
172
|
-
throw new Error('Invalid encrypted data length');
|
|
158
|
+
// Add padding if needed
|
|
159
|
+
const padLength = 4 - (base64.length % 4);
|
|
160
|
+
if (padLength < 4) {
|
|
161
|
+
base64 += '='.repeat(padLength);
|
|
173
162
|
}
|
|
174
|
-
//
|
|
175
|
-
const
|
|
176
|
-
const
|
|
177
|
-
const ciphertext = CryptoJS.lib.WordArray.create(combined.words.slice((finalConfig.ivLength + finalConfig.saltLength) / 4));
|
|
178
|
-
// Derive key using PBKDF2
|
|
179
|
-
const derivedKey = this.deriveKey(key, salt, finalConfig);
|
|
163
|
+
// Derive key and IV
|
|
164
|
+
const aesKey = this.deriveKey(key);
|
|
165
|
+
const iv = this.createDeterministicIV(key);
|
|
180
166
|
// Decrypt the data
|
|
181
|
-
const
|
|
167
|
+
const encryptedWA = CryptoJS.enc.Base64.parse(base64);
|
|
168
|
+
const decrypted = CryptoJS.AES.decrypt({ ciphertext: encryptedWA }, aesKey, {
|
|
182
169
|
iv: iv,
|
|
183
170
|
mode: CryptoJS.mode.CBC,
|
|
184
171
|
padding: CryptoJS.pad.Pkcs7
|
|
185
172
|
});
|
|
186
173
|
// Parse JSON
|
|
187
174
|
const decryptedStr = decrypted.toString(CryptoJS.enc.Utf8);
|
|
175
|
+
if (!decryptedStr) {
|
|
176
|
+
throw new error_control_model_1.DyFM_Error({
|
|
177
|
+
status: 401,
|
|
178
|
+
message: 'Failed to decrypt data - invalid key or corrupted data',
|
|
179
|
+
errorCode: 'DyFM-CRY-DEC-FAIL'
|
|
180
|
+
});
|
|
181
|
+
}
|
|
188
182
|
return this.safeDeserialize(decryptedStr);
|
|
189
183
|
}
|
|
190
184
|
catch (error) {
|
|
@@ -194,25 +188,6 @@ class DyFM_Crypto {
|
|
|
194
188
|
});
|
|
195
189
|
}
|
|
196
190
|
}
|
|
197
|
-
/**
|
|
198
|
-
* Generates a secure random key
|
|
199
|
-
* @param length Length of the key in bytes (default: 32)
|
|
200
|
-
* @returns A secure random key
|
|
201
|
-
*/
|
|
202
|
-
static generateKey(length = 32) {
|
|
203
|
-
return CryptoJS.lib.WordArray.random(length).toString();
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Validates if a string is a valid encrypted data
|
|
207
|
-
* @param encryptedData The data to validate
|
|
208
|
-
* @returns true if the data appears to be valid encrypted data
|
|
209
|
-
*/
|
|
210
|
-
static isValidEncryptedData(encryptedData) {
|
|
211
|
-
if (!encryptedData || typeof encryptedData !== 'string') {
|
|
212
|
-
return false;
|
|
213
|
-
}
|
|
214
|
-
return /^[A-Za-z0-9\-_]+$/.test(encryptedData);
|
|
215
|
-
}
|
|
216
191
|
/**
|
|
217
192
|
* Gets default error settings
|
|
218
193
|
*/
|