@etsoo/appscript 1.1.70 → 1.1.71

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
@@ -434,10 +449,17 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
434
449
  * Decrypt message
435
450
  * @param messageEncrypted Encrypted message
436
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
437
459
  * @param durationSeconds Duration seconds, <= 12 will be considered as month
438
460
  * @returns Pure text
439
461
  */
440
- decrypt(messageEncrypted: string, passphrase?: string, durationSeconds?: number): string | undefined;
462
+ decryptEnhanced(messageEncrypted: string, passphrase?: string, durationSeconds?: number): string | undefined;
441
463
  /**
442
464
  * Detect IP data, call only one time
443
465
  * @param callback Callback will be called when the IP is ready
@@ -452,6 +474,14 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
452
474
  * @returns Result
453
475
  */
454
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;
455
485
  /**
456
486
  * Enchance secret passphrase
457
487
  * @param passphrase Secret passphrase
@@ -170,7 +170,7 @@ class CoreApp {
170
170
  return;
171
171
  // Decrypt
172
172
  // Should be done within 120 seconds after returning from the backend
173
- const passphrase = this.decrypt(data.passphrase, timestamp.toString(), 120);
173
+ const passphrase = this.decrypt(data.passphrase, timestamp.toString());
174
174
  if (passphrase == null)
175
175
  return;
176
176
  // Update device id and cache it
@@ -180,17 +180,17 @@ class CoreApp {
180
180
  this.passphrase = passphrase;
181
181
  // Previous passphrase
182
182
  if (data.previousPassphrase) {
183
- const prev = this.decrypt(data.previousPassphrase, timestamp.toString(), 120);
183
+ const prev = this.decrypt(data.previousPassphrase, timestamp.toString());
184
184
  // Update
185
185
  const fields = this.initCallUpdateFields();
186
186
  for (const field of fields) {
187
187
  const currentValue = shared_1.StorageUtils.getLocalData(field, '');
188
188
  if (currentValue === '' || currentValue.indexOf('+') === -1)
189
189
  continue;
190
- const newValueSource = this.decrypt(currentValue, prev, 12);
190
+ const newValueSource = this.decryptEnhanced(currentValue, prev, 12);
191
191
  if (newValueSource == null)
192
192
  continue;
193
- const newValue = this.encrypt(newValueSource);
193
+ const newValue = this.encryptEnhanced(newValueSource);
194
194
  shared_1.StorageUtils.setLocalData(field, newValue);
195
195
  }
196
196
  }
@@ -294,16 +294,40 @@ class CoreApp {
294
294
  * Decrypt message
295
295
  * @param messageEncrypted Encrypted message
296
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
297
322
  * @param durationSeconds Duration seconds, <= 12 will be considered as month
298
323
  * @returns Pure text
299
324
  */
300
- decrypt(messageEncrypted, passphrase, durationSeconds) {
325
+ decryptEnhanced(messageEncrypted, passphrase, durationSeconds) {
301
326
  // Timestamp splitter
302
327
  const pos = messageEncrypted.indexOf('+');
303
328
  if (pos === -1 || messageEncrypted.length <= 66)
304
329
  return undefined;
305
330
  const timestamp = messageEncrypted.substring(0, pos);
306
- const message = messageEncrypted.substring(pos + 1);
307
331
  if (durationSeconds != null && durationSeconds > 0) {
308
332
  const milseconds = shared_1.Utils.charsToNumber(timestamp);
309
333
  if (isNaN(milseconds) || milseconds < 1)
@@ -315,23 +339,9 @@ class CoreApp {
315
339
  timespan.totalSeconds > durationSeconds))
316
340
  return undefined;
317
341
  }
318
- // Iterations
319
- const iterations = parseInt(message.substring(0, 2), 10);
320
- if (isNaN(iterations))
321
- return undefined;
322
- const salt = crypto_js_1.enc.Hex.parse(message.substring(2, 34));
323
- const iv = crypto_js_1.enc.Hex.parse(message.substring(34, 66));
324
- const encrypted = message.substring(66);
325
- const key = (0, crypto_js_1.PBKDF2)(this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp), salt, {
326
- keySize: 8,
327
- hasher: crypto_js_1.algo.SHA256,
328
- iterations: 1000 * iterations
329
- });
330
- return crypto_js_1.AES.decrypt(encrypted, key, {
331
- iv,
332
- padding: crypto_js_1.pad.Pkcs7,
333
- mode: crypto_js_1.mode.CBC
334
- }).toString(crypto_js_1.enc.Utf8);
342
+ const message = messageEncrypted.substring(pos + 1);
343
+ passphrase = this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp);
344
+ return this.decrypt(message, passphrase);
335
345
  }
336
346
  /**
337
347
  * Detect IP data, call only one time
@@ -376,19 +386,15 @@ class CoreApp {
376
386
  encrypt(message, passphrase, iterations) {
377
387
  // Default 1 * 1000
378
388
  iterations !== null && iterations !== void 0 ? iterations : (iterations = 1);
379
- // Timestamp
380
- const timestamp = shared_1.Utils.numberToChars(new Date().getTime());
381
389
  const bits = 16; // 128 / 8
382
390
  const salt = crypto_js_1.lib.WordArray.random(bits);
383
- const key = (0, crypto_js_1.PBKDF2)(this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp), salt, {
391
+ const key = (0, crypto_js_1.PBKDF2)(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, salt, {
384
392
  keySize: 8,
385
393
  hasher: crypto_js_1.algo.SHA256,
386
394
  iterations: 1000 * iterations
387
395
  });
388
396
  const iv = crypto_js_1.lib.WordArray.random(bits);
389
- return (timestamp +
390
- '+' +
391
- iterations.toString().padStart(2, '0') +
397
+ return (iterations.toString().padStart(2, '0') +
392
398
  salt.toString(crypto_js_1.enc.Hex) +
393
399
  iv.toString(crypto_js_1.enc.Hex) +
394
400
  crypto_js_1.AES.encrypt(message, key, {
@@ -398,6 +404,19 @@ class CoreApp {
398
404
  }).toString() // enc.Base64
399
405
  );
400
406
  }
407
+ /**
408
+ * Enhanced encrypt message
409
+ * @param message Message
410
+ * @param passphrase Secret passphrase
411
+ * @param iterations Iterations, 1000 times, 1 - 99
412
+ * @returns Result
413
+ */
414
+ encryptEnhanced(message, passphrase, iterations) {
415
+ // Timestamp
416
+ const timestamp = shared_1.Utils.numberToChars(new Date().getTime());
417
+ passphrase = this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp);
418
+ return timestamp + '+' + this.encrypt(message, passphrase, iterations);
419
+ }
401
420
  /**
402
421
  * Enchance secret passphrase
403
422
  * @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
@@ -434,10 +449,17 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
434
449
  * Decrypt message
435
450
  * @param messageEncrypted Encrypted message
436
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
437
459
  * @param durationSeconds Duration seconds, <= 12 will be considered as month
438
460
  * @returns Pure text
439
461
  */
440
- decrypt(messageEncrypted: string, passphrase?: string, durationSeconds?: number): string | undefined;
462
+ decryptEnhanced(messageEncrypted: string, passphrase?: string, durationSeconds?: number): string | undefined;
441
463
  /**
442
464
  * Detect IP data, call only one time
443
465
  * @param callback Callback will be called when the IP is ready
@@ -452,6 +474,14 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
452
474
  * @returns Result
453
475
  */
454
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;
455
485
  /**
456
486
  * Enchance secret passphrase
457
487
  * @param passphrase Secret passphrase
@@ -167,7 +167,7 @@ export class CoreApp {
167
167
  return;
168
168
  // Decrypt
169
169
  // Should be done within 120 seconds after returning from the backend
170
- const passphrase = this.decrypt(data.passphrase, timestamp.toString(), 120);
170
+ const passphrase = this.decrypt(data.passphrase, timestamp.toString());
171
171
  if (passphrase == null)
172
172
  return;
173
173
  // Update device id and cache it
@@ -177,17 +177,17 @@ export class CoreApp {
177
177
  this.passphrase = passphrase;
178
178
  // Previous passphrase
179
179
  if (data.previousPassphrase) {
180
- const prev = this.decrypt(data.previousPassphrase, timestamp.toString(), 120);
180
+ const prev = this.decrypt(data.previousPassphrase, timestamp.toString());
181
181
  // Update
182
182
  const fields = this.initCallUpdateFields();
183
183
  for (const field of fields) {
184
184
  const currentValue = StorageUtils.getLocalData(field, '');
185
185
  if (currentValue === '' || currentValue.indexOf('+') === -1)
186
186
  continue;
187
- const newValueSource = this.decrypt(currentValue, prev, 12);
187
+ const newValueSource = this.decryptEnhanced(currentValue, prev, 12);
188
188
  if (newValueSource == null)
189
189
  continue;
190
- const newValue = this.encrypt(newValueSource);
190
+ const newValue = this.encryptEnhanced(newValueSource);
191
191
  StorageUtils.setLocalData(field, newValue);
192
192
  }
193
193
  }
@@ -291,16 +291,40 @@ export class CoreApp {
291
291
  * Decrypt message
292
292
  * @param messageEncrypted Encrypted message
293
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
294
319
  * @param durationSeconds Duration seconds, <= 12 will be considered as month
295
320
  * @returns Pure text
296
321
  */
297
- decrypt(messageEncrypted, passphrase, durationSeconds) {
322
+ decryptEnhanced(messageEncrypted, passphrase, durationSeconds) {
298
323
  // Timestamp splitter
299
324
  const pos = messageEncrypted.indexOf('+');
300
325
  if (pos === -1 || messageEncrypted.length <= 66)
301
326
  return undefined;
302
327
  const timestamp = messageEncrypted.substring(0, pos);
303
- const message = messageEncrypted.substring(pos + 1);
304
328
  if (durationSeconds != null && durationSeconds > 0) {
305
329
  const milseconds = Utils.charsToNumber(timestamp);
306
330
  if (isNaN(milseconds) || milseconds < 1)
@@ -312,23 +336,9 @@ export class CoreApp {
312
336
  timespan.totalSeconds > durationSeconds))
313
337
  return undefined;
314
338
  }
315
- // Iterations
316
- const iterations = parseInt(message.substring(0, 2), 10);
317
- if (isNaN(iterations))
318
- return undefined;
319
- const salt = enc.Hex.parse(message.substring(2, 34));
320
- const iv = enc.Hex.parse(message.substring(34, 66));
321
- const encrypted = message.substring(66);
322
- const key = PBKDF2(this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp), salt, {
323
- keySize: 8,
324
- hasher: algo.SHA256,
325
- iterations: 1000 * iterations
326
- });
327
- return AES.decrypt(encrypted, key, {
328
- iv,
329
- padding: pad.Pkcs7,
330
- mode: mode.CBC
331
- }).toString(enc.Utf8);
339
+ const message = messageEncrypted.substring(pos + 1);
340
+ passphrase = this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp);
341
+ return this.decrypt(message, passphrase);
332
342
  }
333
343
  /**
334
344
  * Detect IP data, call only one time
@@ -373,19 +383,15 @@ export class CoreApp {
373
383
  encrypt(message, passphrase, iterations) {
374
384
  // Default 1 * 1000
375
385
  iterations !== null && iterations !== void 0 ? iterations : (iterations = 1);
376
- // Timestamp
377
- const timestamp = Utils.numberToChars(new Date().getTime());
378
386
  const bits = 16; // 128 / 8
379
387
  const salt = lib.WordArray.random(bits);
380
- const key = PBKDF2(this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp), salt, {
388
+ const key = PBKDF2(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, salt, {
381
389
  keySize: 8,
382
390
  hasher: algo.SHA256,
383
391
  iterations: 1000 * iterations
384
392
  });
385
393
  const iv = lib.WordArray.random(bits);
386
- return (timestamp +
387
- '+' +
388
- iterations.toString().padStart(2, '0') +
394
+ return (iterations.toString().padStart(2, '0') +
389
395
  salt.toString(enc.Hex) +
390
396
  iv.toString(enc.Hex) +
391
397
  AES.encrypt(message, key, {
@@ -395,6 +401,19 @@ export class CoreApp {
395
401
  }).toString() // enc.Base64
396
402
  );
397
403
  }
404
+ /**
405
+ * Enhanced encrypt message
406
+ * @param message Message
407
+ * @param passphrase Secret passphrase
408
+ * @param iterations Iterations, 1000 times, 1 - 99
409
+ * @returns Result
410
+ */
411
+ encryptEnhanced(message, passphrase, iterations) {
412
+ // Timestamp
413
+ const timestamp = Utils.numberToChars(new Date().getTime());
414
+ passphrase = this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp);
415
+ return timestamp + '+' + this.encrypt(message, passphrase, iterations);
416
+ }
398
417
  /**
399
418
  * Enchance secret passphrase
400
419
  * @param passphrase Secret passphrase
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/appscript",
3
- "version": "1.1.70",
3
+ "version": "1.1.71",
4
4
  "description": "Applications shared TypeScript framework",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -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
@@ -655,11 +676,7 @@ export abstract class CoreApp<
655
676
 
656
677
  // Decrypt
657
678
  // Should be done within 120 seconds after returning from the backend
658
- const passphrase = this.decrypt(
659
- data.passphrase,
660
- timestamp.toString(),
661
- 120
662
- );
679
+ const passphrase = this.decrypt(data.passphrase, timestamp.toString());
663
680
  if (passphrase == null) return;
664
681
 
665
682
  // Update device id and cache it
@@ -673,8 +690,7 @@ export abstract class CoreApp<
673
690
  if (data.previousPassphrase) {
674
691
  const prev = this.decrypt(
675
692
  data.previousPassphrase,
676
- timestamp.toString(),
677
- 120
693
+ timestamp.toString()
678
694
  );
679
695
 
680
696
  // Update
@@ -687,10 +703,14 @@ export abstract class CoreApp<
687
703
  if (currentValue === '' || currentValue.indexOf('+') === -1)
688
704
  continue;
689
705
 
690
- const newValueSource = this.decrypt(currentValue, prev, 12);
706
+ const newValueSource = this.decryptEnhanced(
707
+ currentValue,
708
+ prev,
709
+ 12
710
+ );
691
711
  if (newValueSource == null) continue;
692
712
 
693
- const newValue = this.encrypt(newValueSource);
713
+ const newValue = this.encryptEnhanced(newValueSource);
694
714
  StorageUtils.setLocalData(field, newValue);
695
715
  }
696
716
  }
@@ -819,10 +839,38 @@ export abstract class CoreApp<
819
839
  * Decrypt message
820
840
  * @param messageEncrypted Encrypted message
821
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
822
870
  * @param durationSeconds Duration seconds, <= 12 will be considered as month
823
871
  * @returns Pure text
824
872
  */
825
- decrypt(
873
+ decryptEnhanced(
826
874
  messageEncrypted: string,
827
875
  passphrase?: string,
828
876
  durationSeconds?: number
@@ -832,7 +880,6 @@ export abstract class CoreApp<
832
880
  if (pos === -1 || messageEncrypted.length <= 66) return undefined;
833
881
 
834
882
  const timestamp = messageEncrypted.substring(0, pos);
835
- const message = messageEncrypted.substring(pos + 1);
836
883
 
837
884
  if (durationSeconds != null && durationSeconds > 0) {
838
885
  const milseconds = Utils.charsToNumber(timestamp);
@@ -847,29 +894,13 @@ export abstract class CoreApp<
847
894
  return undefined;
848
895
  }
849
896
 
850
- // Iterations
851
- const iterations = parseInt(message.substring(0, 2), 10);
852
- if (isNaN(iterations)) return undefined;
853
-
854
- const salt = enc.Hex.parse(message.substring(2, 34));
855
- const iv = enc.Hex.parse(message.substring(34, 66));
856
- const encrypted = message.substring(66);
857
-
858
- const key = PBKDF2(
859
- this.encryptionEnhance(passphrase ?? this.passphrase, timestamp),
860
- salt,
861
- {
862
- keySize: 8, // 256 / 32
863
- hasher: algo.SHA256,
864
- iterations: 1000 * iterations
865
- }
897
+ const message = messageEncrypted.substring(pos + 1);
898
+ passphrase = this.encryptionEnhance(
899
+ passphrase ?? this.passphrase,
900
+ timestamp
866
901
  );
867
902
 
868
- return AES.decrypt(encrypted, key, {
869
- iv,
870
- padding: pad.Pkcs7,
871
- mode: mode.CBC
872
- }).toString(enc.Utf8);
903
+ return this.decrypt(message, passphrase);
873
904
  }
874
905
 
875
906
  /**
@@ -923,25 +954,16 @@ export abstract class CoreApp<
923
954
  // Default 1 * 1000
924
955
  iterations ??= 1;
925
956
 
926
- // Timestamp
927
- const timestamp = Utils.numberToChars(new Date().getTime());
928
-
929
957
  const bits = 16; // 128 / 8
930
958
  const salt = lib.WordArray.random(bits);
931
- const key = PBKDF2(
932
- this.encryptionEnhance(passphrase ?? this.passphrase, timestamp),
933
- salt,
934
- {
935
- keySize: 8, // 256 / 32
936
- hasher: algo.SHA256,
937
- iterations: 1000 * iterations
938
- }
939
- );
959
+ const key = PBKDF2(passphrase ?? this.passphrase, salt, {
960
+ keySize: 8, // 256 / 32
961
+ hasher: algo.SHA256,
962
+ iterations: 1000 * iterations
963
+ });
940
964
  const iv = lib.WordArray.random(bits);
941
965
 
942
966
  return (
943
- timestamp +
944
- '+' +
945
967
  iterations.toString().padStart(2, '0') +
946
968
  salt.toString(enc.Hex) +
947
969
  iv.toString(enc.Hex) +
@@ -953,6 +975,25 @@ export abstract class CoreApp<
953
975
  );
954
976
  }
955
977
 
978
+ /**
979
+ * Enhanced encrypt message
980
+ * @param message Message
981
+ * @param passphrase Secret passphrase
982
+ * @param iterations Iterations, 1000 times, 1 - 99
983
+ * @returns Result
984
+ */
985
+ encryptEnhanced(message: string, passphrase?: string, iterations?: number) {
986
+ // Timestamp
987
+ const timestamp = Utils.numberToChars(new Date().getTime());
988
+
989
+ passphrase = this.encryptionEnhance(
990
+ passphrase ?? this.passphrase,
991
+ timestamp
992
+ );
993
+
994
+ return timestamp + '+' + this.encrypt(message, passphrase, iterations);
995
+ }
996
+
956
997
  /**
957
998
  * Enchance secret passphrase
958
999
  * @param passphrase Secret passphrase