@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.
- package/__tests__/app/CoreApp.ts +20 -0
- package/lib/cjs/app/CoreApp.d.ts +32 -2
- package/lib/cjs/app/CoreApp.js +48 -29
- package/lib/mjs/app/CoreApp.d.ts +32 -2
- package/lib/mjs/app/CoreApp.js +48 -29
- package/package.json +1 -1
- package/src/app/CoreApp.ts +88 -47
package/__tests__/app/CoreApp.ts
CHANGED
|
@@ -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
|
+
});
|
package/lib/cjs/app/CoreApp.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
package/lib/cjs/app/CoreApp.js
CHANGED
|
@@ -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()
|
|
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()
|
|
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.
|
|
190
|
+
const newValueSource = this.decryptEnhanced(currentValue, prev, 12);
|
|
191
191
|
if (newValueSource == null)
|
|
192
192
|
continue;
|
|
193
|
-
const newValue = this.
|
|
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
|
-
|
|
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
|
-
|
|
319
|
-
|
|
320
|
-
|
|
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)(
|
|
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 (
|
|
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
|
package/lib/mjs/app/CoreApp.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
package/lib/mjs/app/CoreApp.js
CHANGED
|
@@ -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()
|
|
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()
|
|
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.
|
|
187
|
+
const newValueSource = this.decryptEnhanced(currentValue, prev, 12);
|
|
188
188
|
if (newValueSource == null)
|
|
189
189
|
continue;
|
|
190
|
-
const newValue = this.
|
|
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
|
-
|
|
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
|
-
|
|
316
|
-
|
|
317
|
-
|
|
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(
|
|
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 (
|
|
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
package/src/app/CoreApp.ts
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
706
|
+
const newValueSource = this.decryptEnhanced(
|
|
707
|
+
currentValue,
|
|
708
|
+
prev,
|
|
709
|
+
12
|
|
710
|
+
);
|
|
691
711
|
if (newValueSource == null) continue;
|
|
692
712
|
|
|
693
|
-
const newValue = this.
|
|
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
|
-
|
|
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
|
-
|
|
851
|
-
|
|
852
|
-
|
|
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
|
|
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
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
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
|