@futdevpro/fsm-dynamo 1.10.30 → 1.10.32

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.
Files changed (33) hide show
  1. package/build/_enums/environment-flag.enum.d.ts +1 -0
  2. package/build/_enums/environment-flag.enum.d.ts.map +1 -1
  3. package/build/_enums/environment-flag.enum.js +2 -1
  4. package/build/_enums/environment-flag.enum.js.map +1 -1
  5. package/build/_models/control-models/data-property-params.control-model.d.ts.map +1 -1
  6. package/build/_models/control-models/data-property-params.control-model.js +18 -6
  7. package/build/_models/control-models/data-property-params.control-model.js.map +1 -1
  8. package/build/_models/control-models/data-property-params.control-model.spec.js +7 -4
  9. package/build/_models/control-models/data-property-params.control-model.spec.js.map +1 -1
  10. package/build/_models/control-models/service-endpoint-settings-base.control-model.js +3 -3
  11. package/build/_modules/crypto/_collections/crypto.util.d.ts +86 -0
  12. package/build/_modules/crypto/_collections/crypto.util.d.ts.map +1 -0
  13. package/build/_modules/crypto/_collections/crypto.util.js +212 -0
  14. package/build/_modules/crypto/_collections/crypto.util.js.map +1 -0
  15. package/build/_modules/crypto/_collections/crypto.util.spec.d.ts +2 -0
  16. package/build/_modules/crypto/_collections/crypto.util.spec.d.ts.map +1 -0
  17. package/build/_modules/crypto/_collections/crypto.util.spec.js +165 -0
  18. package/build/_modules/crypto/_collections/crypto.util.spec.js.map +1 -0
  19. package/build/_modules/crypto/index.d.ts +2 -0
  20. package/build/_modules/crypto/index.d.ts.map +1 -0
  21. package/build/_modules/crypto/index.js +5 -0
  22. package/build/_modules/crypto/index.js.map +1 -0
  23. package/futdevpro-fsm-dynamo-01.10.32.tgz +0 -0
  24. package/nodemon.json +7 -2
  25. package/package.json +20 -6
  26. package/src/_enums/environment-flag.enum.ts +2 -0
  27. package/src/_models/control-models/data-property-params.control-model.spec.ts +7 -4
  28. package/src/_models/control-models/data-property-params.control-model.ts +18 -6
  29. package/src/_models/control-models/service-endpoint-settings-base.control-model.ts +3 -3
  30. package/src/_modules/crypto/_collections/crypto.util.spec.ts +195 -0
  31. package/src/_modules/crypto/_collections/crypto.util.ts +248 -0
  32. package/src/_modules/crypto/index.ts +3 -0
  33. package/futdevpro-fsm-dynamo-01.10.30.tgz +0 -0
@@ -0,0 +1,248 @@
1
+ import * as CryptoJS from 'crypto-js';
2
+
3
+ import { DyFM_Error } from '../../../_models/control-models/error.control-model';
4
+
5
+ /**
6
+ * Error codes for crypto operations
7
+ */
8
+ export enum CryptoErrorCode {
9
+ INVALID_INPUT = 'DyFM-CRY-EA0',
10
+ DECRYPTION_FAILED = 'DyFM-CRY-DRY',
11
+ ENCRYPTION_FAILED = 'DyFM-CRY-ENF',
12
+ INVALID_KEY = 'DyFM-CRY-IKY',
13
+ INVALID_DATA = 'DyFM-CRY-IDT'
14
+ }
15
+
16
+ /**
17
+ * Configuration options for encryption/decryption
18
+ */
19
+ export interface CryptoConfig {
20
+ ivLength?: number;
21
+ saltLength?: number;
22
+ keyIterations?: number;
23
+ keySize?: number;
24
+ }
25
+
26
+ /**
27
+ * A utility class for secure encryption and decryption of data
28
+ * Uses AES-256-CBC with PBKDF2 key derivation
29
+ */
30
+ export class DyFM_Crypto {
31
+ private static readonly DEFAULT_CONFIG: Required<CryptoConfig> = {
32
+ ivLength: 16,
33
+ saltLength: 16,
34
+ keyIterations: 10000,
35
+ keySize: 256 / 32
36
+ };
37
+
38
+ // Tömör: kb. 60–80 karakteres token, nem 200+
39
+ // Nem szabványos: nehéz visszafejteni
40
+ // Használható cookie, header, URL-ben
41
+
42
+ /**
43
+ * Validates the input data and key
44
+ * @throws {DyFM_Error} if validation fails
45
+ */
46
+ private static validateInput<T>(data: T, key: string): void {
47
+ if (data === undefined || data === null) {
48
+ throw new DyFM_Error({
49
+ message: 'Data is required',
50
+ error: new Error('Data is required'),
51
+ errorCode: CryptoErrorCode.INVALID_DATA
52
+ });
53
+ }
54
+
55
+ if (!key || typeof key !== 'string' || key.trim().length === 0) {
56
+ throw new DyFM_Error({
57
+ message: 'Valid key is required',
58
+ error: new Error('Key must be a non-empty string'),
59
+ errorCode: CryptoErrorCode.INVALID_KEY
60
+ });
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Generates a secure random padding
66
+ * @param length Length of the padding in bytes
67
+ */
68
+ private static generatePadding(length: number): string {
69
+ return CryptoJS.lib.WordArray.random(length).toString();
70
+ }
71
+
72
+ /**
73
+ * Derives a key using PBKDF2
74
+ * @param key The input key
75
+ * @param salt The salt to use
76
+ * @param config Configuration options
77
+ */
78
+ private static deriveKey(key: string, salt: CryptoJS.lib.WordArray, config: Required<CryptoConfig>): CryptoJS.lib.WordArray {
79
+ return CryptoJS.PBKDF2(key, salt, {
80
+ keySize: config.keySize,
81
+ iterations: config.keyIterations
82
+ });
83
+ }
84
+
85
+ /**
86
+ * Safely serializes data to JSON
87
+ * @param data The data to serialize
88
+ * @returns Serialized data as string
89
+ */
90
+ private static safeSerialize<T>(data: T): string {
91
+ try {
92
+ return JSON.stringify(data);
93
+ } catch (error) {
94
+ throw new DyFM_Error({
95
+ message: 'Failed to serialize data',
96
+ error: error instanceof Error ? error : new Error(String(error)),
97
+ errorCode: CryptoErrorCode.INVALID_DATA
98
+ });
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Safely deserializes JSON data
104
+ * @param data The JSON string to deserialize
105
+ * @returns Deserialized data
106
+ */
107
+ private static safeDeserialize<T>(data: string): T {
108
+ try {
109
+ return JSON.parse(data);
110
+ } catch (error) {
111
+ throw new DyFM_Error({
112
+ message: 'Failed to deserialize data',
113
+ error: error instanceof Error ? error : new Error(String(error)),
114
+ errorCode: CryptoErrorCode.DECRYPTION_FAILED
115
+ });
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Encrypts data using AES-256-CBC
121
+ * @param data The data to encrypt
122
+ * @param key The encryption key
123
+ * @param config Optional configuration
124
+ * @returns URL-safe encrypted string
125
+ * @throws {DyFM_Error} if encryption fails
126
+ */
127
+ static encrypt<T>(data: T, key: string, config?: CryptoConfig): string {
128
+ try {
129
+ this.validateInput(data, key);
130
+ const finalConfig = { ...this.DEFAULT_CONFIG, ...config };
131
+
132
+ // Generate random IV and salt
133
+ const iv = CryptoJS.lib.WordArray.random(finalConfig.ivLength);
134
+ const salt = CryptoJS.lib.WordArray.random(finalConfig.saltLength);
135
+
136
+ // Derive key using PBKDF2
137
+ const derivedKey = this.deriveKey(key, salt, finalConfig);
138
+
139
+ // Convert data to string and add random padding
140
+ const dataStr = this.safeSerialize(data);
141
+ const padding = this.generatePadding(16);
142
+ const paddedData = padding + dataStr;
143
+
144
+ // Encrypt the data
145
+ const encrypted = CryptoJS.AES.encrypt(paddedData, derivedKey, {
146
+ iv: iv,
147
+ mode: CryptoJS.mode.CBC,
148
+ padding: CryptoJS.pad.Pkcs7
149
+ });
150
+
151
+ // Combine IV + Salt + Ciphertext
152
+ const combined = iv.concat(salt).concat(encrypted.ciphertext);
153
+
154
+ // Convert to URL-safe base64
155
+ return CryptoJS.enc.Base64.stringify(combined)
156
+ .replace(/\+/g, '-')
157
+ .replace(/\//g, '_')
158
+ .replace(/=+$/, '');
159
+ } catch (error) {
160
+ throw new DyFM_Error({
161
+ message: 'Error encrypting data',
162
+ error: error instanceof Error ? error : new Error(String(error)),
163
+ errorCode: CryptoErrorCode.ENCRYPTION_FAILED
164
+ });
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Decrypts data that was encrypted using encrypt()
170
+ * @param encryptedData The encrypted data
171
+ * @param key The decryption key
172
+ * @param config Optional configuration
173
+ * @returns The decrypted data
174
+ * @throws {DyFM_Error} if decryption fails
175
+ */
176
+ static decrypt<T>(encryptedData: string, key: string, config?: CryptoConfig): T {
177
+ try {
178
+ this.validateInput(encryptedData, key);
179
+ const finalConfig = { ...this.DEFAULT_CONFIG, ...config };
180
+
181
+ // Convert from URL-safe base64
182
+ const base64 = encryptedData
183
+ .replace(/-/g, '+')
184
+ .replace(/_/g, '/');
185
+
186
+ // Parse the combined data
187
+ const combined = CryptoJS.enc.Base64.parse(base64);
188
+
189
+ // Extract IV, salt, and ciphertext
190
+ const iv = CryptoJS.lib.WordArray.create(combined.words.slice(0, finalConfig.ivLength / 4));
191
+ const salt = CryptoJS.lib.WordArray.create(
192
+ combined.words.slice(
193
+ finalConfig.ivLength / 4,
194
+ (finalConfig.ivLength + finalConfig.saltLength) / 4
195
+ )
196
+ );
197
+ const ciphertext = CryptoJS.lib.WordArray.create(
198
+ combined.words.slice((finalConfig.ivLength + finalConfig.saltLength) / 4)
199
+ );
200
+
201
+ // Derive key using PBKDF2
202
+ const derivedKey = this.deriveKey(key, salt, finalConfig);
203
+
204
+ // Decrypt the data
205
+ const decrypted = CryptoJS.AES.decrypt(
206
+ { ciphertext: ciphertext },
207
+ derivedKey,
208
+ {
209
+ iv: iv,
210
+ mode: CryptoJS.mode.CBC,
211
+ padding: CryptoJS.pad.Pkcs7
212
+ }
213
+ );
214
+
215
+ // Remove padding and parse JSON
216
+ const decryptedStr = decrypted.toString(CryptoJS.enc.Utf8);
217
+ const jsonStr = decryptedStr.slice(32); // Remove 16-byte padding
218
+ return this.safeDeserialize<T>(jsonStr);
219
+ } catch (error) {
220
+ throw new DyFM_Error({
221
+ message: 'Error decrypting data',
222
+ error: error instanceof Error ? error : new Error(String(error)),
223
+ errorCode: CryptoErrorCode.DECRYPTION_FAILED
224
+ });
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Generates a secure random key
230
+ * @param length Length of the key in bytes (default: 32)
231
+ * @returns A secure random key
232
+ */
233
+ static generateKey(length: number = 32): string {
234
+ return CryptoJS.lib.WordArray.random(length).toString();
235
+ }
236
+
237
+ /**
238
+ * Validates if a string is a valid encrypted data
239
+ * @param encryptedData The data to validate
240
+ * @returns true if the data appears to be valid encrypted data
241
+ */
242
+ static isValidEncryptedData(encryptedData: string): boolean {
243
+ if (!encryptedData || typeof encryptedData !== 'string') {
244
+ return false;
245
+ }
246
+ return /^[A-Za-z0-9\-_]+$/.test(encryptedData);
247
+ }
248
+ }
@@ -0,0 +1,3 @@
1
+
2
+
3
+ export * from './_collections/crypto.util';
Binary file