@etsoo/appscript 1.1.69 → 1.1.73
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 +53 -31
- package/lib/mjs/app/CoreApp.d.ts +32 -2
- package/lib/mjs/app/CoreApp.js +53 -31
- package/package.json +4 -4
- package/src/app/CoreApp.ts +95 -49
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
|
@@ -154,6 +154,8 @@ class CoreApp {
|
|
|
154
154
|
}
|
|
155
155
|
if (callback)
|
|
156
156
|
callback(false);
|
|
157
|
+
// Clear device id
|
|
158
|
+
shared_1.StorageUtils.setLocalData(this.deviceIdField, null);
|
|
157
159
|
return;
|
|
158
160
|
}
|
|
159
161
|
this.initCallUpdate(result.data, data.timestamp);
|
|
@@ -170,7 +172,7 @@ class CoreApp {
|
|
|
170
172
|
return;
|
|
171
173
|
// Decrypt
|
|
172
174
|
// Should be done within 120 seconds after returning from the backend
|
|
173
|
-
const passphrase = this.decrypt(data.passphrase, timestamp.toString()
|
|
175
|
+
const passphrase = this.decrypt(data.passphrase, timestamp.toString());
|
|
174
176
|
if (passphrase == null)
|
|
175
177
|
return;
|
|
176
178
|
// Update device id and cache it
|
|
@@ -180,17 +182,17 @@ class CoreApp {
|
|
|
180
182
|
this.passphrase = passphrase;
|
|
181
183
|
// Previous passphrase
|
|
182
184
|
if (data.previousPassphrase) {
|
|
183
|
-
const prev = this.decrypt(data.previousPassphrase, timestamp.toString()
|
|
185
|
+
const prev = this.decrypt(data.previousPassphrase, timestamp.toString());
|
|
184
186
|
// Update
|
|
185
187
|
const fields = this.initCallUpdateFields();
|
|
186
188
|
for (const field of fields) {
|
|
187
189
|
const currentValue = shared_1.StorageUtils.getLocalData(field, '');
|
|
188
190
|
if (currentValue === '' || currentValue.indexOf('+') === -1)
|
|
189
191
|
continue;
|
|
190
|
-
const newValueSource = this.
|
|
192
|
+
const newValueSource = this.decryptEnhanced(currentValue, prev, 12);
|
|
191
193
|
if (newValueSource == null)
|
|
192
194
|
continue;
|
|
193
|
-
const newValue = this.
|
|
195
|
+
const newValue = this.encryptEnhanced(newValueSource);
|
|
194
196
|
shared_1.StorageUtils.setLocalData(field, newValue);
|
|
195
197
|
}
|
|
196
198
|
}
|
|
@@ -294,16 +296,41 @@ class CoreApp {
|
|
|
294
296
|
* Decrypt message
|
|
295
297
|
* @param messageEncrypted Encrypted message
|
|
296
298
|
* @param passphrase Secret passphrase
|
|
299
|
+
* @returns Pure text
|
|
300
|
+
*/
|
|
301
|
+
decrypt(messageEncrypted, passphrase) {
|
|
302
|
+
// Iterations
|
|
303
|
+
const iterations = parseInt(messageEncrypted.substring(0, 2), 10);
|
|
304
|
+
if (isNaN(iterations))
|
|
305
|
+
return undefined;
|
|
306
|
+
const salt = crypto_js_1.enc.Hex.parse(messageEncrypted.substring(2, 34));
|
|
307
|
+
const iv = crypto_js_1.enc.Hex.parse(messageEncrypted.substring(34, 66));
|
|
308
|
+
const encrypted = messageEncrypted.substring(66);
|
|
309
|
+
const key = (0, crypto_js_1.PBKDF2)(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, salt, {
|
|
310
|
+
keySize: 8,
|
|
311
|
+
hasher: crypto_js_1.algo.SHA256,
|
|
312
|
+
iterations: 1000 * iterations
|
|
313
|
+
});
|
|
314
|
+
return crypto_js_1.AES.decrypt(encrypted, key, {
|
|
315
|
+
iv,
|
|
316
|
+
padding: crypto_js_1.pad.Pkcs7,
|
|
317
|
+
mode: crypto_js_1.mode.CBC
|
|
318
|
+
}).toString(crypto_js_1.enc.Utf8);
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Enhanced decrypt message
|
|
322
|
+
* @param messageEncrypted Encrypted message
|
|
323
|
+
* @param passphrase Secret passphrase
|
|
297
324
|
* @param durationSeconds Duration seconds, <= 12 will be considered as month
|
|
298
325
|
* @returns Pure text
|
|
299
326
|
*/
|
|
300
|
-
|
|
327
|
+
decryptEnhanced(messageEncrypted, passphrase, durationSeconds) {
|
|
301
328
|
// Timestamp splitter
|
|
302
|
-
const pos = messageEncrypted.indexOf('
|
|
303
|
-
|
|
329
|
+
const pos = messageEncrypted.indexOf('!');
|
|
330
|
+
// Miliseconds chars are longer than 8
|
|
331
|
+
if (pos < 8 || messageEncrypted.length <= 66)
|
|
304
332
|
return undefined;
|
|
305
333
|
const timestamp = messageEncrypted.substring(0, pos);
|
|
306
|
-
const message = messageEncrypted.substring(pos + 1);
|
|
307
334
|
if (durationSeconds != null && durationSeconds > 0) {
|
|
308
335
|
const milseconds = shared_1.Utils.charsToNumber(timestamp);
|
|
309
336
|
if (isNaN(milseconds) || milseconds < 1)
|
|
@@ -315,23 +342,9 @@ class CoreApp {
|
|
|
315
342
|
timespan.totalSeconds > durationSeconds))
|
|
316
343
|
return undefined;
|
|
317
344
|
}
|
|
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);
|
|
345
|
+
const message = messageEncrypted.substring(pos + 1);
|
|
346
|
+
passphrase = this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp);
|
|
347
|
+
return this.decrypt(message, passphrase);
|
|
335
348
|
}
|
|
336
349
|
/**
|
|
337
350
|
* Detect IP data, call only one time
|
|
@@ -376,19 +389,15 @@ class CoreApp {
|
|
|
376
389
|
encrypt(message, passphrase, iterations) {
|
|
377
390
|
// Default 1 * 1000
|
|
378
391
|
iterations !== null && iterations !== void 0 ? iterations : (iterations = 1);
|
|
379
|
-
// Timestamp
|
|
380
|
-
const timestamp = shared_1.Utils.numberToChars(new Date().getTime());
|
|
381
392
|
const bits = 16; // 128 / 8
|
|
382
393
|
const salt = crypto_js_1.lib.WordArray.random(bits);
|
|
383
|
-
const key = (0, crypto_js_1.PBKDF2)(
|
|
394
|
+
const key = (0, crypto_js_1.PBKDF2)(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, salt, {
|
|
384
395
|
keySize: 8,
|
|
385
396
|
hasher: crypto_js_1.algo.SHA256,
|
|
386
397
|
iterations: 1000 * iterations
|
|
387
398
|
});
|
|
388
399
|
const iv = crypto_js_1.lib.WordArray.random(bits);
|
|
389
|
-
return (
|
|
390
|
-
'+' +
|
|
391
|
-
iterations.toString().padStart(2, '0') +
|
|
400
|
+
return (iterations.toString().padStart(2, '0') +
|
|
392
401
|
salt.toString(crypto_js_1.enc.Hex) +
|
|
393
402
|
iv.toString(crypto_js_1.enc.Hex) +
|
|
394
403
|
crypto_js_1.AES.encrypt(message, key, {
|
|
@@ -398,6 +407,19 @@ class CoreApp {
|
|
|
398
407
|
}).toString() // enc.Base64
|
|
399
408
|
);
|
|
400
409
|
}
|
|
410
|
+
/**
|
|
411
|
+
* Enhanced encrypt message
|
|
412
|
+
* @param message Message
|
|
413
|
+
* @param passphrase Secret passphrase
|
|
414
|
+
* @param iterations Iterations, 1000 times, 1 - 99
|
|
415
|
+
* @returns Result
|
|
416
|
+
*/
|
|
417
|
+
encryptEnhanced(message, passphrase, iterations) {
|
|
418
|
+
// Timestamp
|
|
419
|
+
const timestamp = shared_1.Utils.numberToChars(new Date().getTime());
|
|
420
|
+
passphrase = this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp);
|
|
421
|
+
return timestamp + '!' + this.encrypt(message, passphrase, iterations);
|
|
422
|
+
}
|
|
401
423
|
/**
|
|
402
424
|
* Enchance secret passphrase
|
|
403
425
|
* @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
|
@@ -151,6 +151,8 @@ export class CoreApp {
|
|
|
151
151
|
}
|
|
152
152
|
if (callback)
|
|
153
153
|
callback(false);
|
|
154
|
+
// Clear device id
|
|
155
|
+
StorageUtils.setLocalData(this.deviceIdField, null);
|
|
154
156
|
return;
|
|
155
157
|
}
|
|
156
158
|
this.initCallUpdate(result.data, data.timestamp);
|
|
@@ -167,7 +169,7 @@ export class CoreApp {
|
|
|
167
169
|
return;
|
|
168
170
|
// Decrypt
|
|
169
171
|
// Should be done within 120 seconds after returning from the backend
|
|
170
|
-
const passphrase = this.decrypt(data.passphrase, timestamp.toString()
|
|
172
|
+
const passphrase = this.decrypt(data.passphrase, timestamp.toString());
|
|
171
173
|
if (passphrase == null)
|
|
172
174
|
return;
|
|
173
175
|
// Update device id and cache it
|
|
@@ -177,17 +179,17 @@ export class CoreApp {
|
|
|
177
179
|
this.passphrase = passphrase;
|
|
178
180
|
// Previous passphrase
|
|
179
181
|
if (data.previousPassphrase) {
|
|
180
|
-
const prev = this.decrypt(data.previousPassphrase, timestamp.toString()
|
|
182
|
+
const prev = this.decrypt(data.previousPassphrase, timestamp.toString());
|
|
181
183
|
// Update
|
|
182
184
|
const fields = this.initCallUpdateFields();
|
|
183
185
|
for (const field of fields) {
|
|
184
186
|
const currentValue = StorageUtils.getLocalData(field, '');
|
|
185
187
|
if (currentValue === '' || currentValue.indexOf('+') === -1)
|
|
186
188
|
continue;
|
|
187
|
-
const newValueSource = this.
|
|
189
|
+
const newValueSource = this.decryptEnhanced(currentValue, prev, 12);
|
|
188
190
|
if (newValueSource == null)
|
|
189
191
|
continue;
|
|
190
|
-
const newValue = this.
|
|
192
|
+
const newValue = this.encryptEnhanced(newValueSource);
|
|
191
193
|
StorageUtils.setLocalData(field, newValue);
|
|
192
194
|
}
|
|
193
195
|
}
|
|
@@ -291,16 +293,41 @@ export class CoreApp {
|
|
|
291
293
|
* Decrypt message
|
|
292
294
|
* @param messageEncrypted Encrypted message
|
|
293
295
|
* @param passphrase Secret passphrase
|
|
296
|
+
* @returns Pure text
|
|
297
|
+
*/
|
|
298
|
+
decrypt(messageEncrypted, passphrase) {
|
|
299
|
+
// Iterations
|
|
300
|
+
const iterations = parseInt(messageEncrypted.substring(0, 2), 10);
|
|
301
|
+
if (isNaN(iterations))
|
|
302
|
+
return undefined;
|
|
303
|
+
const salt = enc.Hex.parse(messageEncrypted.substring(2, 34));
|
|
304
|
+
const iv = enc.Hex.parse(messageEncrypted.substring(34, 66));
|
|
305
|
+
const encrypted = messageEncrypted.substring(66);
|
|
306
|
+
const key = PBKDF2(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, salt, {
|
|
307
|
+
keySize: 8,
|
|
308
|
+
hasher: algo.SHA256,
|
|
309
|
+
iterations: 1000 * iterations
|
|
310
|
+
});
|
|
311
|
+
return AES.decrypt(encrypted, key, {
|
|
312
|
+
iv,
|
|
313
|
+
padding: pad.Pkcs7,
|
|
314
|
+
mode: mode.CBC
|
|
315
|
+
}).toString(enc.Utf8);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Enhanced decrypt message
|
|
319
|
+
* @param messageEncrypted Encrypted message
|
|
320
|
+
* @param passphrase Secret passphrase
|
|
294
321
|
* @param durationSeconds Duration seconds, <= 12 will be considered as month
|
|
295
322
|
* @returns Pure text
|
|
296
323
|
*/
|
|
297
|
-
|
|
324
|
+
decryptEnhanced(messageEncrypted, passphrase, durationSeconds) {
|
|
298
325
|
// Timestamp splitter
|
|
299
|
-
const pos = messageEncrypted.indexOf('
|
|
300
|
-
|
|
326
|
+
const pos = messageEncrypted.indexOf('!');
|
|
327
|
+
// Miliseconds chars are longer than 8
|
|
328
|
+
if (pos < 8 || messageEncrypted.length <= 66)
|
|
301
329
|
return undefined;
|
|
302
330
|
const timestamp = messageEncrypted.substring(0, pos);
|
|
303
|
-
const message = messageEncrypted.substring(pos + 1);
|
|
304
331
|
if (durationSeconds != null && durationSeconds > 0) {
|
|
305
332
|
const milseconds = Utils.charsToNumber(timestamp);
|
|
306
333
|
if (isNaN(milseconds) || milseconds < 1)
|
|
@@ -312,23 +339,9 @@ export class CoreApp {
|
|
|
312
339
|
timespan.totalSeconds > durationSeconds))
|
|
313
340
|
return undefined;
|
|
314
341
|
}
|
|
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);
|
|
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);
|
|
332
345
|
}
|
|
333
346
|
/**
|
|
334
347
|
* Detect IP data, call only one time
|
|
@@ -373,19 +386,15 @@ export class CoreApp {
|
|
|
373
386
|
encrypt(message, passphrase, iterations) {
|
|
374
387
|
// Default 1 * 1000
|
|
375
388
|
iterations !== null && iterations !== void 0 ? iterations : (iterations = 1);
|
|
376
|
-
// Timestamp
|
|
377
|
-
const timestamp = Utils.numberToChars(new Date().getTime());
|
|
378
389
|
const bits = 16; // 128 / 8
|
|
379
390
|
const salt = lib.WordArray.random(bits);
|
|
380
|
-
const key = PBKDF2(
|
|
391
|
+
const key = PBKDF2(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, salt, {
|
|
381
392
|
keySize: 8,
|
|
382
393
|
hasher: algo.SHA256,
|
|
383
394
|
iterations: 1000 * iterations
|
|
384
395
|
});
|
|
385
396
|
const iv = lib.WordArray.random(bits);
|
|
386
|
-
return (
|
|
387
|
-
'+' +
|
|
388
|
-
iterations.toString().padStart(2, '0') +
|
|
397
|
+
return (iterations.toString().padStart(2, '0') +
|
|
389
398
|
salt.toString(enc.Hex) +
|
|
390
399
|
iv.toString(enc.Hex) +
|
|
391
400
|
AES.encrypt(message, key, {
|
|
@@ -395,6 +404,19 @@ export class CoreApp {
|
|
|
395
404
|
}).toString() // enc.Base64
|
|
396
405
|
);
|
|
397
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 = 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
|
+
}
|
|
398
420
|
/**
|
|
399
421
|
* Enchance secret passphrase
|
|
400
422
|
* @param passphrase Secret passphrase
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/appscript",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.73",
|
|
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.
|
|
74
|
-
"ts-jest": "^27.1.
|
|
75
|
-
"typescript": "^4.5.
|
|
73
|
+
"jest": "^27.4.4",
|
|
74
|
+
"ts-jest": "^27.1.1",
|
|
75
|
+
"typescript": "^4.5.3"
|
|
76
76
|
}
|
|
77
77
|
}
|
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
|
|
@@ -637,6 +658,9 @@ export abstract class CoreApp<
|
|
|
637
658
|
|
|
638
659
|
if (callback) callback(false);
|
|
639
660
|
|
|
661
|
+
// Clear device id
|
|
662
|
+
StorageUtils.setLocalData(this.deviceIdField, null);
|
|
663
|
+
|
|
640
664
|
return;
|
|
641
665
|
}
|
|
642
666
|
|
|
@@ -655,11 +679,7 @@ export abstract class CoreApp<
|
|
|
655
679
|
|
|
656
680
|
// Decrypt
|
|
657
681
|
// 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
|
-
);
|
|
682
|
+
const passphrase = this.decrypt(data.passphrase, timestamp.toString());
|
|
663
683
|
if (passphrase == null) return;
|
|
664
684
|
|
|
665
685
|
// Update device id and cache it
|
|
@@ -673,8 +693,7 @@ export abstract class CoreApp<
|
|
|
673
693
|
if (data.previousPassphrase) {
|
|
674
694
|
const prev = this.decrypt(
|
|
675
695
|
data.previousPassphrase,
|
|
676
|
-
timestamp.toString()
|
|
677
|
-
120
|
|
696
|
+
timestamp.toString()
|
|
678
697
|
);
|
|
679
698
|
|
|
680
699
|
// Update
|
|
@@ -687,10 +706,14 @@ export abstract class CoreApp<
|
|
|
687
706
|
if (currentValue === '' || currentValue.indexOf('+') === -1)
|
|
688
707
|
continue;
|
|
689
708
|
|
|
690
|
-
const newValueSource = this.
|
|
709
|
+
const newValueSource = this.decryptEnhanced(
|
|
710
|
+
currentValue,
|
|
711
|
+
prev,
|
|
712
|
+
12
|
|
713
|
+
);
|
|
691
714
|
if (newValueSource == null) continue;
|
|
692
715
|
|
|
693
|
-
const newValue = this.
|
|
716
|
+
const newValue = this.encryptEnhanced(newValueSource);
|
|
694
717
|
StorageUtils.setLocalData(field, newValue);
|
|
695
718
|
}
|
|
696
719
|
}
|
|
@@ -819,20 +842,49 @@ export abstract class CoreApp<
|
|
|
819
842
|
* Decrypt message
|
|
820
843
|
* @param messageEncrypted Encrypted message
|
|
821
844
|
* @param passphrase Secret passphrase
|
|
845
|
+
* @returns Pure text
|
|
846
|
+
*/
|
|
847
|
+
decrypt(messageEncrypted: string, passphrase?: string) {
|
|
848
|
+
// Iterations
|
|
849
|
+
const iterations = parseInt(messageEncrypted.substring(0, 2), 10);
|
|
850
|
+
if (isNaN(iterations)) return undefined;
|
|
851
|
+
|
|
852
|
+
const salt = enc.Hex.parse(messageEncrypted.substring(2, 34));
|
|
853
|
+
const iv = enc.Hex.parse(messageEncrypted.substring(34, 66));
|
|
854
|
+
const encrypted = messageEncrypted.substring(66);
|
|
855
|
+
|
|
856
|
+
const key = PBKDF2(passphrase ?? this.passphrase, salt, {
|
|
857
|
+
keySize: 8, // 256 / 32
|
|
858
|
+
hasher: algo.SHA256,
|
|
859
|
+
iterations: 1000 * iterations
|
|
860
|
+
});
|
|
861
|
+
|
|
862
|
+
return AES.decrypt(encrypted, key, {
|
|
863
|
+
iv,
|
|
864
|
+
padding: pad.Pkcs7,
|
|
865
|
+
mode: mode.CBC
|
|
866
|
+
}).toString(enc.Utf8);
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* Enhanced decrypt message
|
|
871
|
+
* @param messageEncrypted Encrypted message
|
|
872
|
+
* @param passphrase Secret passphrase
|
|
822
873
|
* @param durationSeconds Duration seconds, <= 12 will be considered as month
|
|
823
874
|
* @returns Pure text
|
|
824
875
|
*/
|
|
825
|
-
|
|
876
|
+
decryptEnhanced(
|
|
826
877
|
messageEncrypted: string,
|
|
827
878
|
passphrase?: string,
|
|
828
879
|
durationSeconds?: number
|
|
829
880
|
) {
|
|
830
881
|
// Timestamp splitter
|
|
831
|
-
const pos = messageEncrypted.indexOf('
|
|
832
|
-
|
|
882
|
+
const pos = messageEncrypted.indexOf('!');
|
|
883
|
+
|
|
884
|
+
// Miliseconds chars are longer than 8
|
|
885
|
+
if (pos < 8 || messageEncrypted.length <= 66) return undefined;
|
|
833
886
|
|
|
834
887
|
const timestamp = messageEncrypted.substring(0, pos);
|
|
835
|
-
const message = messageEncrypted.substring(pos + 1);
|
|
836
888
|
|
|
837
889
|
if (durationSeconds != null && durationSeconds > 0) {
|
|
838
890
|
const milseconds = Utils.charsToNumber(timestamp);
|
|
@@ -847,29 +899,13 @@ export abstract class CoreApp<
|
|
|
847
899
|
return undefined;
|
|
848
900
|
}
|
|
849
901
|
|
|
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
|
-
}
|
|
902
|
+
const message = messageEncrypted.substring(pos + 1);
|
|
903
|
+
passphrase = this.encryptionEnhance(
|
|
904
|
+
passphrase ?? this.passphrase,
|
|
905
|
+
timestamp
|
|
866
906
|
);
|
|
867
907
|
|
|
868
|
-
return
|
|
869
|
-
iv,
|
|
870
|
-
padding: pad.Pkcs7,
|
|
871
|
-
mode: mode.CBC
|
|
872
|
-
}).toString(enc.Utf8);
|
|
908
|
+
return this.decrypt(message, passphrase);
|
|
873
909
|
}
|
|
874
910
|
|
|
875
911
|
/**
|
|
@@ -923,25 +959,16 @@ export abstract class CoreApp<
|
|
|
923
959
|
// Default 1 * 1000
|
|
924
960
|
iterations ??= 1;
|
|
925
961
|
|
|
926
|
-
// Timestamp
|
|
927
|
-
const timestamp = Utils.numberToChars(new Date().getTime());
|
|
928
|
-
|
|
929
962
|
const bits = 16; // 128 / 8
|
|
930
963
|
const salt = lib.WordArray.random(bits);
|
|
931
|
-
const key = PBKDF2(
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
hasher: algo.SHA256,
|
|
937
|
-
iterations: 1000 * iterations
|
|
938
|
-
}
|
|
939
|
-
);
|
|
964
|
+
const key = PBKDF2(passphrase ?? this.passphrase, salt, {
|
|
965
|
+
keySize: 8, // 256 / 32
|
|
966
|
+
hasher: algo.SHA256,
|
|
967
|
+
iterations: 1000 * iterations
|
|
968
|
+
});
|
|
940
969
|
const iv = lib.WordArray.random(bits);
|
|
941
970
|
|
|
942
971
|
return (
|
|
943
|
-
timestamp +
|
|
944
|
-
'+' +
|
|
945
972
|
iterations.toString().padStart(2, '0') +
|
|
946
973
|
salt.toString(enc.Hex) +
|
|
947
974
|
iv.toString(enc.Hex) +
|
|
@@ -953,6 +980,25 @@ export abstract class CoreApp<
|
|
|
953
980
|
);
|
|
954
981
|
}
|
|
955
982
|
|
|
983
|
+
/**
|
|
984
|
+
* Enhanced encrypt message
|
|
985
|
+
* @param message Message
|
|
986
|
+
* @param passphrase Secret passphrase
|
|
987
|
+
* @param iterations Iterations, 1000 times, 1 - 99
|
|
988
|
+
* @returns Result
|
|
989
|
+
*/
|
|
990
|
+
encryptEnhanced(message: string, passphrase?: string, iterations?: number) {
|
|
991
|
+
// Timestamp
|
|
992
|
+
const timestamp = Utils.numberToChars(new Date().getTime());
|
|
993
|
+
|
|
994
|
+
passphrase = this.encryptionEnhance(
|
|
995
|
+
passphrase ?? this.passphrase,
|
|
996
|
+
timestamp
|
|
997
|
+
);
|
|
998
|
+
|
|
999
|
+
return timestamp + '!' + this.encrypt(message, passphrase, iterations);
|
|
1000
|
+
}
|
|
1001
|
+
|
|
956
1002
|
/**
|
|
957
1003
|
* Enchance secret passphrase
|
|
958
1004
|
* @param passphrase Secret passphrase
|