@etsoo/appscript 1.1.68 → 1.1.72

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.
@@ -12,6 +12,7 @@ import { AddressUtils } from '../../src/address/AddressUtils';
12
12
  import { IAppSettings } from '../../src/app/AppSettings';
13
13
  import { CoreApp } from '../../src/app/CoreApp';
14
14
  import { zhCN } from '../../src/i18n/zhCN';
15
+ import { InitCallResultData } from '../../src/result/InitCallResult';
15
16
 
16
17
  // Detected country or region
17
18
  const { detectedCountry } = DomUtils;
@@ -108,6 +109,11 @@ class CoreAppTest extends CoreApp<IAppSettings, {}, NotificationCallProps> {
108
109
  freshCountdownUI(callback?: () => PromiseLike<unknown>): void {
109
110
  throw new Error('Method not implemented.');
110
111
  }
112
+
113
+ initCallUpdateLocal(data: InitCallResultData, timestamp: number) {
114
+ this.initCallUpdate(data, timestamp);
115
+ return this.passphrase;
116
+ }
111
117
  }
112
118
 
113
119
  const app = new CoreAppTest();
@@ -122,3 +128,17 @@ test('Tests for encrypt / decrypt', () => {
122
128
  const plain = app.decrypt(encrypted, passphrase);
123
129
  expect(plain).toEqual(input);
124
130
  });
131
+
132
+ test('Tests for initCallUpdateLocal', () => {
133
+ // Act
134
+ const passphrase = app.initCallUpdateLocal(
135
+ {
136
+ deviceId:
137
+ 'ZmNjZlov+10067A1520126643352C2022735B85DC8F380088468402C98A5631A8CFBE14E134zXfxmw77lFopTTlbqOfsK2KUqPSsTAQb35Ejrm1BAvUaQH3SuZcwGYu3+PQ/Rd56',
138
+ passphrase:
139
+ '01397BF28A93FC031BC8B9B808F880F12C398AB792DF2ADE7A8768CADD2259EB50HJuKhqGuLQO+SmvCVzuEGUN4TdkUuPMWR0E6lliszbNiXboCziXx5SdfX3lMpoBX'
140
+ },
141
+ 1639282438620
142
+ );
143
+ expect(passphrase).not.toBeNull();
144
+ });
@@ -118,10 +118,17 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
118
118
  * Decrypt message
119
119
  * @param messageEncrypted Encrypted message
120
120
  * @param passphrase Secret passphrase
121
+ * @returns Pure text
122
+ */
123
+ decrypt(messageEncrypted: string, passphrase?: string): string | undefined;
124
+ /**
125
+ * Enhanced decrypt message
126
+ * @param messageEncrypted Encrypted message
127
+ * @param passphrase Secret passphrase
121
128
  * @param durationSeconds Duration seconds, <= 12 will be considered as month
122
129
  * @returns Pure text
123
130
  */
124
- decrypt(messageEncrypted: string, passphrase?: string, durationSeconds?: number): string | undefined;
131
+ decryptEnhanced(messageEncrypted: string, passphrase?: string, durationSeconds?: number): string | undefined;
125
132
  /**
126
133
  * Detect IP data, call only one time
127
134
  * @param callback Callback will be called when the IP is ready
@@ -135,6 +142,14 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
135
142
  * @returns Result
136
143
  */
137
144
  encrypt(message: string, passphrase?: string, iterations?: number): string;
145
+ /**
146
+ * Enhanced encrypt message
147
+ * @param message Message
148
+ * @param passphrase Secret passphrase
149
+ * @param iterations Iterations, 1000 times, 1 - 99
150
+ * @returns Result
151
+ */
152
+ encryptEnhanced(message: string, passphrase?: string, iterations?: number): string;
138
153
  /**
139
154
  * Format date to string
140
155
  * @param input Input date
@@ -235,6 +250,12 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
235
250
  * @returns Result
236
251
  */
237
252
  hasPermission(roles: number | UserRole | number[] | UserRole[]): boolean;
253
+ /**
254
+ * Init call
255
+ * @param callback Callback
256
+ * @returns Result
257
+ */
258
+ initCall(callback?: (result: boolean) => void): Promise<void>;
238
259
  /**
239
260
  * Callback where exit a page
240
261
  */
@@ -387,9 +408,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
387
408
  protected setApi(api: IApi): void;
388
409
  /**
389
410
  * Init call
411
+ * @param callback Callback
390
412
  * @returns Result
391
413
  */
392
- protected initCall(): Promise<void>;
414
+ initCall(callback?: (result: boolean) => void): Promise<void>;
393
415
  /**
394
416
  * Init call update
395
417
  * @param data Result data
@@ -427,10 +449,17 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
427
449
  * Decrypt message
428
450
  * @param messageEncrypted Encrypted message
429
451
  * @param passphrase Secret passphrase
452
+ * @returns Pure text
453
+ */
454
+ decrypt(messageEncrypted: string, passphrase?: string): string | undefined;
455
+ /**
456
+ * Enhanced decrypt message
457
+ * @param messageEncrypted Encrypted message
458
+ * @param passphrase Secret passphrase
430
459
  * @param durationSeconds Duration seconds, <= 12 will be considered as month
431
460
  * @returns Pure text
432
461
  */
433
- decrypt(messageEncrypted: string, passphrase?: string, durationSeconds?: number): string | undefined;
462
+ decryptEnhanced(messageEncrypted: string, passphrase?: string, durationSeconds?: number): string | undefined;
434
463
  /**
435
464
  * Detect IP data, call only one time
436
465
  * @param callback Callback will be called when the IP is ready
@@ -445,6 +474,14 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
445
474
  * @returns Result
446
475
  */
447
476
  encrypt(message: string, passphrase?: string, iterations?: number): string;
477
+ /**
478
+ * Enhanced encrypt message
479
+ * @param message Message
480
+ * @param passphrase Secret passphrase
481
+ * @param iterations Iterations, 1000 times, 1 - 99
482
+ * @returns Result
483
+ */
484
+ encryptEnhanced(message: string, passphrase?: string, iterations?: number): string;
448
485
  /**
449
486
  * Enchance secret passphrase
450
487
  * @param passphrase Secret passphrase
@@ -119,19 +119,25 @@ class CoreApp {
119
119
  }
120
120
  /**
121
121
  * Init call
122
+ * @param callback Callback
122
123
  * @returns Result
123
124
  */
124
- async initCall() {
125
+ async initCall(callback) {
125
126
  var _a;
126
127
  const data = {
127
128
  timestamp: new Date().getTime(),
128
129
  deviceId: this.deviceId === '' ? undefined : this.deviceId
129
130
  };
130
131
  const result = await this.api.put('Auth/WebInitCall', data);
131
- if (result == null)
132
+ if (result == null) {
133
+ if (callback)
134
+ callback(false);
132
135
  return;
136
+ }
133
137
  if (result.data == null) {
134
138
  this.notifier.alert(this.get('noData'));
139
+ if (callback)
140
+ callback(false);
135
141
  return;
136
142
  }
137
143
  if (!result.ok) {
@@ -146,9 +152,13 @@ class CoreApp {
146
152
  else {
147
153
  this.alertResult(result);
148
154
  }
155
+ if (callback)
156
+ callback(false);
149
157
  return;
150
158
  }
151
159
  this.initCallUpdate(result.data, data.timestamp);
160
+ if (callback)
161
+ callback(true);
152
162
  }
153
163
  /**
154
164
  * Init call update
@@ -160,7 +170,7 @@ class CoreApp {
160
170
  return;
161
171
  // Decrypt
162
172
  // Should be done within 120 seconds after returning from the backend
163
- const passphrase = this.decrypt(data.passphrase, timestamp.toString(), 120);
173
+ const passphrase = this.decrypt(data.passphrase, timestamp.toString());
164
174
  if (passphrase == null)
165
175
  return;
166
176
  // Update device id and cache it
@@ -170,17 +180,17 @@ class CoreApp {
170
180
  this.passphrase = passphrase;
171
181
  // Previous passphrase
172
182
  if (data.previousPassphrase) {
173
- const prev = this.decrypt(data.previousPassphrase, timestamp.toString(), 120);
183
+ const prev = this.decrypt(data.previousPassphrase, timestamp.toString());
174
184
  // Update
175
185
  const fields = this.initCallUpdateFields();
176
186
  for (const field of fields) {
177
187
  const currentValue = shared_1.StorageUtils.getLocalData(field, '');
178
188
  if (currentValue === '' || currentValue.indexOf('+') === -1)
179
189
  continue;
180
- const newValueSource = this.decrypt(currentValue, prev, 12);
190
+ const newValueSource = this.decryptEnhanced(currentValue, prev, 12);
181
191
  if (newValueSource == null)
182
192
  continue;
183
- const newValue = this.encrypt(newValueSource);
193
+ const newValue = this.encryptEnhanced(newValueSource);
184
194
  shared_1.StorageUtils.setLocalData(field, newValue);
185
195
  }
186
196
  }
@@ -284,16 +294,41 @@ class CoreApp {
284
294
  * Decrypt message
285
295
  * @param messageEncrypted Encrypted message
286
296
  * @param passphrase Secret passphrase
297
+ * @returns Pure text
298
+ */
299
+ decrypt(messageEncrypted, passphrase) {
300
+ // Iterations
301
+ const iterations = parseInt(messageEncrypted.substring(0, 2), 10);
302
+ if (isNaN(iterations))
303
+ return undefined;
304
+ const salt = crypto_js_1.enc.Hex.parse(messageEncrypted.substring(2, 34));
305
+ const iv = crypto_js_1.enc.Hex.parse(messageEncrypted.substring(34, 66));
306
+ const encrypted = messageEncrypted.substring(66);
307
+ const key = (0, crypto_js_1.PBKDF2)(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, salt, {
308
+ keySize: 8,
309
+ hasher: crypto_js_1.algo.SHA256,
310
+ iterations: 1000 * iterations
311
+ });
312
+ return crypto_js_1.AES.decrypt(encrypted, key, {
313
+ iv,
314
+ padding: crypto_js_1.pad.Pkcs7,
315
+ mode: crypto_js_1.mode.CBC
316
+ }).toString(crypto_js_1.enc.Utf8);
317
+ }
318
+ /**
319
+ * Enhanced decrypt message
320
+ * @param messageEncrypted Encrypted message
321
+ * @param passphrase Secret passphrase
287
322
  * @param durationSeconds Duration seconds, <= 12 will be considered as month
288
323
  * @returns Pure text
289
324
  */
290
- decrypt(messageEncrypted, passphrase, durationSeconds) {
325
+ decryptEnhanced(messageEncrypted, passphrase, durationSeconds) {
291
326
  // Timestamp splitter
292
- const pos = messageEncrypted.indexOf('+');
293
- if (pos === -1 || messageEncrypted.length <= 66)
327
+ const pos = messageEncrypted.indexOf('!');
328
+ // Miliseconds chars are longer than 8
329
+ if (pos < 8 || messageEncrypted.length <= 66)
294
330
  return undefined;
295
331
  const timestamp = messageEncrypted.substring(0, pos);
296
- const message = messageEncrypted.substring(pos + 1);
297
332
  if (durationSeconds != null && durationSeconds > 0) {
298
333
  const milseconds = shared_1.Utils.charsToNumber(timestamp);
299
334
  if (isNaN(milseconds) || milseconds < 1)
@@ -305,23 +340,9 @@ class CoreApp {
305
340
  timespan.totalSeconds > durationSeconds))
306
341
  return undefined;
307
342
  }
308
- // Iterations
309
- const iterations = parseInt(message.substring(0, 2), 10);
310
- if (isNaN(iterations))
311
- return undefined;
312
- const salt = crypto_js_1.enc.Hex.parse(message.substring(2, 34));
313
- const iv = crypto_js_1.enc.Hex.parse(message.substring(34, 66));
314
- const encrypted = message.substring(66);
315
- const key = (0, crypto_js_1.PBKDF2)(this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp), salt, {
316
- keySize: 8,
317
- hasher: crypto_js_1.algo.SHA256,
318
- iterations: 1000 * iterations
319
- });
320
- return crypto_js_1.AES.decrypt(encrypted, key, {
321
- iv,
322
- padding: crypto_js_1.pad.Pkcs7,
323
- mode: crypto_js_1.mode.CBC
324
- }).toString(crypto_js_1.enc.Utf8);
343
+ const message = messageEncrypted.substring(pos + 1);
344
+ passphrase = this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp);
345
+ return this.decrypt(message, passphrase);
325
346
  }
326
347
  /**
327
348
  * Detect IP data, call only one time
@@ -366,19 +387,15 @@ class CoreApp {
366
387
  encrypt(message, passphrase, iterations) {
367
388
  // Default 1 * 1000
368
389
  iterations !== null && iterations !== void 0 ? iterations : (iterations = 1);
369
- // Timestamp
370
- const timestamp = shared_1.Utils.numberToChars(new Date().getTime());
371
390
  const bits = 16; // 128 / 8
372
391
  const salt = crypto_js_1.lib.WordArray.random(bits);
373
- const key = (0, crypto_js_1.PBKDF2)(this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp), salt, {
392
+ const key = (0, crypto_js_1.PBKDF2)(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, salt, {
374
393
  keySize: 8,
375
394
  hasher: crypto_js_1.algo.SHA256,
376
395
  iterations: 1000 * iterations
377
396
  });
378
397
  const iv = crypto_js_1.lib.WordArray.random(bits);
379
- return (timestamp +
380
- '+' +
381
- iterations.toString().padStart(2, '0') +
398
+ return (iterations.toString().padStart(2, '0') +
382
399
  salt.toString(crypto_js_1.enc.Hex) +
383
400
  iv.toString(crypto_js_1.enc.Hex) +
384
401
  crypto_js_1.AES.encrypt(message, key, {
@@ -388,6 +405,19 @@ class CoreApp {
388
405
  }).toString() // enc.Base64
389
406
  );
390
407
  }
408
+ /**
409
+ * Enhanced encrypt message
410
+ * @param message Message
411
+ * @param passphrase Secret passphrase
412
+ * @param iterations Iterations, 1000 times, 1 - 99
413
+ * @returns Result
414
+ */
415
+ encryptEnhanced(message, passphrase, iterations) {
416
+ // Timestamp
417
+ const timestamp = shared_1.Utils.numberToChars(new Date().getTime());
418
+ passphrase = this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp);
419
+ return timestamp + '!' + this.encrypt(message, passphrase, iterations);
420
+ }
391
421
  /**
392
422
  * Enchance secret passphrase
393
423
  * @param passphrase Secret passphrase
@@ -118,10 +118,17 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
118
118
  * Decrypt message
119
119
  * @param messageEncrypted Encrypted message
120
120
  * @param passphrase Secret passphrase
121
+ * @returns Pure text
122
+ */
123
+ decrypt(messageEncrypted: string, passphrase?: string): string | undefined;
124
+ /**
125
+ * Enhanced decrypt message
126
+ * @param messageEncrypted Encrypted message
127
+ * @param passphrase Secret passphrase
121
128
  * @param durationSeconds Duration seconds, <= 12 will be considered as month
122
129
  * @returns Pure text
123
130
  */
124
- decrypt(messageEncrypted: string, passphrase?: string, durationSeconds?: number): string | undefined;
131
+ decryptEnhanced(messageEncrypted: string, passphrase?: string, durationSeconds?: number): string | undefined;
125
132
  /**
126
133
  * Detect IP data, call only one time
127
134
  * @param callback Callback will be called when the IP is ready
@@ -135,6 +142,14 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
135
142
  * @returns Result
136
143
  */
137
144
  encrypt(message: string, passphrase?: string, iterations?: number): string;
145
+ /**
146
+ * Enhanced encrypt message
147
+ * @param message Message
148
+ * @param passphrase Secret passphrase
149
+ * @param iterations Iterations, 1000 times, 1 - 99
150
+ * @returns Result
151
+ */
152
+ encryptEnhanced(message: string, passphrase?: string, iterations?: number): string;
138
153
  /**
139
154
  * Format date to string
140
155
  * @param input Input date
@@ -235,6 +250,12 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
235
250
  * @returns Result
236
251
  */
237
252
  hasPermission(roles: number | UserRole | number[] | UserRole[]): boolean;
253
+ /**
254
+ * Init call
255
+ * @param callback Callback
256
+ * @returns Result
257
+ */
258
+ initCall(callback?: (result: boolean) => void): Promise<void>;
238
259
  /**
239
260
  * Callback where exit a page
240
261
  */
@@ -387,9 +408,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
387
408
  protected setApi(api: IApi): void;
388
409
  /**
389
410
  * Init call
411
+ * @param callback Callback
390
412
  * @returns Result
391
413
  */
392
- protected initCall(): Promise<void>;
414
+ initCall(callback?: (result: boolean) => void): Promise<void>;
393
415
  /**
394
416
  * Init call update
395
417
  * @param data Result data
@@ -427,10 +449,17 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
427
449
  * Decrypt message
428
450
  * @param messageEncrypted Encrypted message
429
451
  * @param passphrase Secret passphrase
452
+ * @returns Pure text
453
+ */
454
+ decrypt(messageEncrypted: string, passphrase?: string): string | undefined;
455
+ /**
456
+ * Enhanced decrypt message
457
+ * @param messageEncrypted Encrypted message
458
+ * @param passphrase Secret passphrase
430
459
  * @param durationSeconds Duration seconds, <= 12 will be considered as month
431
460
  * @returns Pure text
432
461
  */
433
- decrypt(messageEncrypted: string, passphrase?: string, durationSeconds?: number): string | undefined;
462
+ decryptEnhanced(messageEncrypted: string, passphrase?: string, durationSeconds?: number): string | undefined;
434
463
  /**
435
464
  * Detect IP data, call only one time
436
465
  * @param callback Callback will be called when the IP is ready
@@ -445,6 +474,14 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
445
474
  * @returns Result
446
475
  */
447
476
  encrypt(message: string, passphrase?: string, iterations?: number): string;
477
+ /**
478
+ * Enhanced encrypt message
479
+ * @param message Message
480
+ * @param passphrase Secret passphrase
481
+ * @param iterations Iterations, 1000 times, 1 - 99
482
+ * @returns Result
483
+ */
484
+ encryptEnhanced(message: string, passphrase?: string, iterations?: number): string;
448
485
  /**
449
486
  * Enchance secret passphrase
450
487
  * @param passphrase Secret passphrase
@@ -116,19 +116,25 @@ export class CoreApp {
116
116
  }
117
117
  /**
118
118
  * Init call
119
+ * @param callback Callback
119
120
  * @returns Result
120
121
  */
121
- async initCall() {
122
+ async initCall(callback) {
122
123
  var _a;
123
124
  const data = {
124
125
  timestamp: new Date().getTime(),
125
126
  deviceId: this.deviceId === '' ? undefined : this.deviceId
126
127
  };
127
128
  const result = await this.api.put('Auth/WebInitCall', data);
128
- if (result == null)
129
+ if (result == null) {
130
+ if (callback)
131
+ callback(false);
129
132
  return;
133
+ }
130
134
  if (result.data == null) {
131
135
  this.notifier.alert(this.get('noData'));
136
+ if (callback)
137
+ callback(false);
132
138
  return;
133
139
  }
134
140
  if (!result.ok) {
@@ -143,9 +149,13 @@ export class CoreApp {
143
149
  else {
144
150
  this.alertResult(result);
145
151
  }
152
+ if (callback)
153
+ callback(false);
146
154
  return;
147
155
  }
148
156
  this.initCallUpdate(result.data, data.timestamp);
157
+ if (callback)
158
+ callback(true);
149
159
  }
150
160
  /**
151
161
  * Init call update
@@ -157,7 +167,7 @@ export class CoreApp {
157
167
  return;
158
168
  // Decrypt
159
169
  // Should be done within 120 seconds after returning from the backend
160
- const passphrase = this.decrypt(data.passphrase, timestamp.toString(), 120);
170
+ const passphrase = this.decrypt(data.passphrase, timestamp.toString());
161
171
  if (passphrase == null)
162
172
  return;
163
173
  // Update device id and cache it
@@ -167,17 +177,17 @@ export class CoreApp {
167
177
  this.passphrase = passphrase;
168
178
  // Previous passphrase
169
179
  if (data.previousPassphrase) {
170
- const prev = this.decrypt(data.previousPassphrase, timestamp.toString(), 120);
180
+ const prev = this.decrypt(data.previousPassphrase, timestamp.toString());
171
181
  // Update
172
182
  const fields = this.initCallUpdateFields();
173
183
  for (const field of fields) {
174
184
  const currentValue = StorageUtils.getLocalData(field, '');
175
185
  if (currentValue === '' || currentValue.indexOf('+') === -1)
176
186
  continue;
177
- const newValueSource = this.decrypt(currentValue, prev, 12);
187
+ const newValueSource = this.decryptEnhanced(currentValue, prev, 12);
178
188
  if (newValueSource == null)
179
189
  continue;
180
- const newValue = this.encrypt(newValueSource);
190
+ const newValue = this.encryptEnhanced(newValueSource);
181
191
  StorageUtils.setLocalData(field, newValue);
182
192
  }
183
193
  }
@@ -281,16 +291,41 @@ export class CoreApp {
281
291
  * Decrypt message
282
292
  * @param messageEncrypted Encrypted message
283
293
  * @param passphrase Secret passphrase
294
+ * @returns Pure text
295
+ */
296
+ decrypt(messageEncrypted, passphrase) {
297
+ // Iterations
298
+ const iterations = parseInt(messageEncrypted.substring(0, 2), 10);
299
+ if (isNaN(iterations))
300
+ return undefined;
301
+ const salt = enc.Hex.parse(messageEncrypted.substring(2, 34));
302
+ const iv = enc.Hex.parse(messageEncrypted.substring(34, 66));
303
+ const encrypted = messageEncrypted.substring(66);
304
+ const key = PBKDF2(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, salt, {
305
+ keySize: 8,
306
+ hasher: algo.SHA256,
307
+ iterations: 1000 * iterations
308
+ });
309
+ return AES.decrypt(encrypted, key, {
310
+ iv,
311
+ padding: pad.Pkcs7,
312
+ mode: mode.CBC
313
+ }).toString(enc.Utf8);
314
+ }
315
+ /**
316
+ * Enhanced decrypt message
317
+ * @param messageEncrypted Encrypted message
318
+ * @param passphrase Secret passphrase
284
319
  * @param durationSeconds Duration seconds, <= 12 will be considered as month
285
320
  * @returns Pure text
286
321
  */
287
- decrypt(messageEncrypted, passphrase, durationSeconds) {
322
+ decryptEnhanced(messageEncrypted, passphrase, durationSeconds) {
288
323
  // Timestamp splitter
289
- const pos = messageEncrypted.indexOf('+');
290
- if (pos === -1 || messageEncrypted.length <= 66)
324
+ const pos = messageEncrypted.indexOf('!');
325
+ // Miliseconds chars are longer than 8
326
+ if (pos < 8 || messageEncrypted.length <= 66)
291
327
  return undefined;
292
328
  const timestamp = messageEncrypted.substring(0, pos);
293
- const message = messageEncrypted.substring(pos + 1);
294
329
  if (durationSeconds != null && durationSeconds > 0) {
295
330
  const milseconds = Utils.charsToNumber(timestamp);
296
331
  if (isNaN(milseconds) || milseconds < 1)
@@ -302,23 +337,9 @@ export class CoreApp {
302
337
  timespan.totalSeconds > durationSeconds))
303
338
  return undefined;
304
339
  }
305
- // Iterations
306
- const iterations = parseInt(message.substring(0, 2), 10);
307
- if (isNaN(iterations))
308
- return undefined;
309
- const salt = enc.Hex.parse(message.substring(2, 34));
310
- const iv = enc.Hex.parse(message.substring(34, 66));
311
- const encrypted = message.substring(66);
312
- const key = PBKDF2(this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp), salt, {
313
- keySize: 8,
314
- hasher: algo.SHA256,
315
- iterations: 1000 * iterations
316
- });
317
- return AES.decrypt(encrypted, key, {
318
- iv,
319
- padding: pad.Pkcs7,
320
- mode: mode.CBC
321
- }).toString(enc.Utf8);
340
+ const message = messageEncrypted.substring(pos + 1);
341
+ passphrase = this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp);
342
+ return this.decrypt(message, passphrase);
322
343
  }
323
344
  /**
324
345
  * Detect IP data, call only one time
@@ -363,19 +384,15 @@ export class CoreApp {
363
384
  encrypt(message, passphrase, iterations) {
364
385
  // Default 1 * 1000
365
386
  iterations !== null && iterations !== void 0 ? iterations : (iterations = 1);
366
- // Timestamp
367
- const timestamp = Utils.numberToChars(new Date().getTime());
368
387
  const bits = 16; // 128 / 8
369
388
  const salt = lib.WordArray.random(bits);
370
- const key = PBKDF2(this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp), salt, {
389
+ const key = PBKDF2(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, salt, {
371
390
  keySize: 8,
372
391
  hasher: algo.SHA256,
373
392
  iterations: 1000 * iterations
374
393
  });
375
394
  const iv = lib.WordArray.random(bits);
376
- return (timestamp +
377
- '+' +
378
- iterations.toString().padStart(2, '0') +
395
+ return (iterations.toString().padStart(2, '0') +
379
396
  salt.toString(enc.Hex) +
380
397
  iv.toString(enc.Hex) +
381
398
  AES.encrypt(message, key, {
@@ -385,6 +402,19 @@ export class CoreApp {
385
402
  }).toString() // enc.Base64
386
403
  );
387
404
  }
405
+ /**
406
+ * Enhanced encrypt message
407
+ * @param message Message
408
+ * @param passphrase Secret passphrase
409
+ * @param iterations Iterations, 1000 times, 1 - 99
410
+ * @returns Result
411
+ */
412
+ encryptEnhanced(message, passphrase, iterations) {
413
+ // Timestamp
414
+ const timestamp = Utils.numberToChars(new Date().getTime());
415
+ passphrase = this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp);
416
+ return timestamp + '!' + this.encrypt(message, passphrase, iterations);
417
+ }
388
418
  /**
389
419
  * Enchance secret passphrase
390
420
  * @param passphrase Secret passphrase
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/appscript",
3
- "version": "1.1.68",
3
+ "version": "1.1.72",
4
4
  "description": "Applications shared TypeScript framework",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -70,8 +70,8 @@
70
70
  "eslint": "^8.4.1",
71
71
  "eslint-config-airbnb-base": "^15.0.0",
72
72
  "eslint-plugin-import": "^2.25.3",
73
- "jest": "^27.4.3",
74
- "ts-jest": "^27.1.0",
75
- "typescript": "^4.5.2"
73
+ "jest": "^27.4.4",
74
+ "ts-jest": "^27.1.1",
75
+ "typescript": "^4.5.3"
76
76
  }
77
77
  }
@@ -177,10 +177,18 @@ export interface ICoreApp<
177
177
  * Decrypt message
178
178
  * @param messageEncrypted Encrypted message
179
179
  * @param passphrase Secret passphrase
180
+ * @returns Pure text
181
+ */
182
+ decrypt(messageEncrypted: string, passphrase?: string): string | undefined;
183
+
184
+ /**
185
+ * Enhanced decrypt message
186
+ * @param messageEncrypted Encrypted message
187
+ * @param passphrase Secret passphrase
180
188
  * @param durationSeconds Duration seconds, <= 12 will be considered as month
181
189
  * @returns Pure text
182
190
  */
183
- decrypt(
191
+ decryptEnhanced(
184
192
  messageEncrypted: string,
185
193
  passphrase?: string,
186
194
  durationSeconds?: number
@@ -201,6 +209,19 @@ export interface ICoreApp<
201
209
  */
202
210
  encrypt(message: string, passphrase?: string, iterations?: number): string;
203
211
 
212
+ /**
213
+ * Enhanced encrypt message
214
+ * @param message Message
215
+ * @param passphrase Secret passphrase
216
+ * @param iterations Iterations, 1000 times, 1 - 99
217
+ * @returns Result
218
+ */
219
+ encryptEnhanced(
220
+ message: string,
221
+ passphrase?: string,
222
+ iterations?: number
223
+ ): string;
224
+
204
225
  /**
205
226
  * Format date to string
206
227
  * @param input Input date
@@ -326,6 +347,13 @@ export interface ICoreApp<
326
347
  */
327
348
  hasPermission(roles: number | UserRole | number[] | UserRole[]): boolean;
328
349
 
350
+ /**
351
+ * Init call
352
+ * @param callback Callback
353
+ * @returns Result
354
+ */
355
+ initCall(callback?: (result: boolean) => void): Promise<void>;
356
+
329
357
  /**
330
358
  * Callback where exit a page
331
359
  */
@@ -588,9 +616,10 @@ export abstract class CoreApp<
588
616
 
589
617
  /**
590
618
  * Init call
619
+ * @param callback Callback
591
620
  * @returns Result
592
621
  */
593
- protected async initCall() {
622
+ async initCall(callback?: (result: boolean) => void) {
594
623
  const data: InitCallDto = {
595
624
  timestamp: new Date().getTime(),
596
625
  deviceId: this.deviceId === '' ? undefined : this.deviceId
@@ -599,10 +628,14 @@ export abstract class CoreApp<
599
628
  'Auth/WebInitCall',
600
629
  data
601
630
  );
602
- if (result == null) return;
631
+ if (result == null) {
632
+ if (callback) callback(false);
633
+ return;
634
+ }
603
635
 
604
636
  if (result.data == null) {
605
637
  this.notifier.alert(this.get<string>('noData')!);
638
+ if (callback) callback(false);
606
639
  return;
607
640
  }
608
641
 
@@ -623,10 +656,14 @@ export abstract class CoreApp<
623
656
  this.alertResult(result);
624
657
  }
625
658
 
659
+ if (callback) callback(false);
660
+
626
661
  return;
627
662
  }
628
663
 
629
664
  this.initCallUpdate(result.data, data.timestamp);
665
+
666
+ if (callback) callback(true);
630
667
  }
631
668
 
632
669
  /**
@@ -639,11 +676,7 @@ export abstract class CoreApp<
639
676
 
640
677
  // Decrypt
641
678
  // Should be done within 120 seconds after returning from the backend
642
- const passphrase = this.decrypt(
643
- data.passphrase,
644
- timestamp.toString(),
645
- 120
646
- );
679
+ const passphrase = this.decrypt(data.passphrase, timestamp.toString());
647
680
  if (passphrase == null) return;
648
681
 
649
682
  // Update device id and cache it
@@ -657,8 +690,7 @@ export abstract class CoreApp<
657
690
  if (data.previousPassphrase) {
658
691
  const prev = this.decrypt(
659
692
  data.previousPassphrase,
660
- timestamp.toString(),
661
- 120
693
+ timestamp.toString()
662
694
  );
663
695
 
664
696
  // Update
@@ -671,10 +703,14 @@ export abstract class CoreApp<
671
703
  if (currentValue === '' || currentValue.indexOf('+') === -1)
672
704
  continue;
673
705
 
674
- const newValueSource = this.decrypt(currentValue, prev, 12);
706
+ const newValueSource = this.decryptEnhanced(
707
+ currentValue,
708
+ prev,
709
+ 12
710
+ );
675
711
  if (newValueSource == null) continue;
676
712
 
677
- const newValue = this.encrypt(newValueSource);
713
+ const newValue = this.encryptEnhanced(newValueSource);
678
714
  StorageUtils.setLocalData(field, newValue);
679
715
  }
680
716
  }
@@ -803,20 +839,49 @@ export abstract class CoreApp<
803
839
  * Decrypt message
804
840
  * @param messageEncrypted Encrypted message
805
841
  * @param passphrase Secret passphrase
842
+ * @returns Pure text
843
+ */
844
+ decrypt(messageEncrypted: string, passphrase?: string) {
845
+ // Iterations
846
+ const iterations = parseInt(messageEncrypted.substring(0, 2), 10);
847
+ if (isNaN(iterations)) return undefined;
848
+
849
+ const salt = enc.Hex.parse(messageEncrypted.substring(2, 34));
850
+ const iv = enc.Hex.parse(messageEncrypted.substring(34, 66));
851
+ const encrypted = messageEncrypted.substring(66);
852
+
853
+ const key = PBKDF2(passphrase ?? this.passphrase, salt, {
854
+ keySize: 8, // 256 / 32
855
+ hasher: algo.SHA256,
856
+ iterations: 1000 * iterations
857
+ });
858
+
859
+ return AES.decrypt(encrypted, key, {
860
+ iv,
861
+ padding: pad.Pkcs7,
862
+ mode: mode.CBC
863
+ }).toString(enc.Utf8);
864
+ }
865
+
866
+ /**
867
+ * Enhanced decrypt message
868
+ * @param messageEncrypted Encrypted message
869
+ * @param passphrase Secret passphrase
806
870
  * @param durationSeconds Duration seconds, <= 12 will be considered as month
807
871
  * @returns Pure text
808
872
  */
809
- decrypt(
873
+ decryptEnhanced(
810
874
  messageEncrypted: string,
811
875
  passphrase?: string,
812
876
  durationSeconds?: number
813
877
  ) {
814
878
  // Timestamp splitter
815
- const pos = messageEncrypted.indexOf('+');
816
- if (pos === -1 || messageEncrypted.length <= 66) return undefined;
879
+ const pos = messageEncrypted.indexOf('!');
880
+
881
+ // Miliseconds chars are longer than 8
882
+ if (pos < 8 || messageEncrypted.length <= 66) return undefined;
817
883
 
818
884
  const timestamp = messageEncrypted.substring(0, pos);
819
- const message = messageEncrypted.substring(pos + 1);
820
885
 
821
886
  if (durationSeconds != null && durationSeconds > 0) {
822
887
  const milseconds = Utils.charsToNumber(timestamp);
@@ -831,29 +896,13 @@ export abstract class CoreApp<
831
896
  return undefined;
832
897
  }
833
898
 
834
- // Iterations
835
- const iterations = parseInt(message.substring(0, 2), 10);
836
- if (isNaN(iterations)) return undefined;
837
-
838
- const salt = enc.Hex.parse(message.substring(2, 34));
839
- const iv = enc.Hex.parse(message.substring(34, 66));
840
- const encrypted = message.substring(66);
841
-
842
- const key = PBKDF2(
843
- this.encryptionEnhance(passphrase ?? this.passphrase, timestamp),
844
- salt,
845
- {
846
- keySize: 8, // 256 / 32
847
- hasher: algo.SHA256,
848
- iterations: 1000 * iterations
849
- }
899
+ const message = messageEncrypted.substring(pos + 1);
900
+ passphrase = this.encryptionEnhance(
901
+ passphrase ?? this.passphrase,
902
+ timestamp
850
903
  );
851
904
 
852
- return AES.decrypt(encrypted, key, {
853
- iv,
854
- padding: pad.Pkcs7,
855
- mode: mode.CBC
856
- }).toString(enc.Utf8);
905
+ return this.decrypt(message, passphrase);
857
906
  }
858
907
 
859
908
  /**
@@ -907,25 +956,16 @@ export abstract class CoreApp<
907
956
  // Default 1 * 1000
908
957
  iterations ??= 1;
909
958
 
910
- // Timestamp
911
- const timestamp = Utils.numberToChars(new Date().getTime());
912
-
913
959
  const bits = 16; // 128 / 8
914
960
  const salt = lib.WordArray.random(bits);
915
- const key = PBKDF2(
916
- this.encryptionEnhance(passphrase ?? this.passphrase, timestamp),
917
- salt,
918
- {
919
- keySize: 8, // 256 / 32
920
- hasher: algo.SHA256,
921
- iterations: 1000 * iterations
922
- }
923
- );
961
+ const key = PBKDF2(passphrase ?? this.passphrase, salt, {
962
+ keySize: 8, // 256 / 32
963
+ hasher: algo.SHA256,
964
+ iterations: 1000 * iterations
965
+ });
924
966
  const iv = lib.WordArray.random(bits);
925
967
 
926
968
  return (
927
- timestamp +
928
- '+' +
929
969
  iterations.toString().padStart(2, '0') +
930
970
  salt.toString(enc.Hex) +
931
971
  iv.toString(enc.Hex) +
@@ -937,6 +977,25 @@ export abstract class CoreApp<
937
977
  );
938
978
  }
939
979
 
980
+ /**
981
+ * Enhanced encrypt message
982
+ * @param message Message
983
+ * @param passphrase Secret passphrase
984
+ * @param iterations Iterations, 1000 times, 1 - 99
985
+ * @returns Result
986
+ */
987
+ encryptEnhanced(message: string, passphrase?: string, iterations?: number) {
988
+ // Timestamp
989
+ const timestamp = Utils.numberToChars(new Date().getTime());
990
+
991
+ passphrase = this.encryptionEnhance(
992
+ passphrase ?? this.passphrase,
993
+ timestamp
994
+ );
995
+
996
+ return timestamp + '!' + this.encrypt(message, passphrase, iterations);
997
+ }
998
+
940
999
  /**
941
1000
  * Enchance secret passphrase
942
1001
  * @param passphrase Secret passphrase