@metamask-previews/keyring-controller 22.0.2-preview-13f36eb8 → 22.0.2-preview-0013a1bd
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/CHANGELOG.md +1 -13
- package/dist/KeyringController.cjs +213 -111
- package/dist/KeyringController.cjs.map +1 -1
- package/dist/KeyringController.d.cts +31 -28
- package/dist/KeyringController.d.cts.map +1 -1
- package/dist/KeyringController.d.mts +31 -28
- package/dist/KeyringController.d.mts.map +1 -1
- package/dist/KeyringController.mjs +213 -111
- package/dist/KeyringController.mjs.map +1 -1
- package/dist/constants.cjs +4 -3
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +4 -3
- package/dist/constants.d.cts.map +1 -1
- package/dist/constants.d.mts +4 -3
- package/dist/constants.d.mts.map +1 -1
- package/dist/constants.mjs +4 -3
- package/dist/constants.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _KeyringController_instances, _KeyringController_controllerOperationMutex, _KeyringController_vaultOperationMutex, _KeyringController_keyringBuilders, _KeyringController_encryptor, _KeyringController_keyrings, _KeyringController_unsupportedKeyrings, _KeyringController_encryptionKey, _KeyringController_qrKeyringStateListener, _KeyringController_registerMessageHandlers, _KeyringController_getKeyringById, _KeyringController_getKeyringByIdOrDefault, _KeyringController_getKeyringMetadata, _KeyringController_getKeyringBuilderForType, _KeyringController_addQRKeyring, _KeyringController_subscribeToQRKeyringEvents, _KeyringController_unsubscribeFromQRKeyringsEvents, _KeyringController_createNewVaultWithKeyring,
|
|
12
|
+
var _KeyringController_instances, _KeyringController_controllerOperationMutex, _KeyringController_vaultOperationMutex, _KeyringController_keyringBuilders, _KeyringController_encryptor, _KeyringController_cacheEncryptionKey, _KeyringController_keyrings, _KeyringController_unsupportedKeyrings, _KeyringController_password, _KeyringController_encryptionKey, _KeyringController_qrKeyringStateListener, _KeyringController_registerMessageHandlers, _KeyringController_getKeyringById, _KeyringController_getKeyringByIdOrDefault, _KeyringController_getKeyringMetadata, _KeyringController_getKeyringBuilderForType, _KeyringController_addQRKeyring, _KeyringController_subscribeToQRKeyringEvents, _KeyringController_unsubscribeFromQRKeyringsEvents, _KeyringController_createNewVaultWithKeyring, _KeyringController_updateCachedEncryptionKey, _KeyringController_verifySeedPhrase, _KeyringController_getUpdatedKeyrings, _KeyringController_getSerializedKeyrings, _KeyringController_getSessionState, _KeyringController_restoreSerializedKeyrings, _KeyringController_unlockKeyrings, _KeyringController_updateVault, _KeyringController_isNewEncryptionAvailable, _KeyringController_isEnvelopeEncryptionEnabled, _KeyringController_getAccountsFromKeyrings, _KeyringController_createKeyringWithFirstAccount, _KeyringController_newKeyring, _KeyringController_createKeyring, _KeyringController_clearKeyrings, _KeyringController_restoreKeyring, _KeyringController_destroyKeyring, _KeyringController_removeEmptyKeyrings, _KeyringController_assertNoDuplicateAccounts, _KeyringController_setUnlocked, _KeyringController_assertIsUnlocked, _KeyringController_persistOrRollback, _KeyringController_withRollback, _KeyringController_assertControllerMutexIsLocked, _KeyringController_withControllerLock, _KeyringController_withVaultLock;
|
|
13
13
|
function $importDefault(module) {
|
|
14
14
|
if (module?.__esModule) {
|
|
15
15
|
return module.default;
|
|
@@ -145,6 +145,17 @@ function assertIsValidPassword(password) {
|
|
|
145
145
|
throw new Error(KeyringControllerError.InvalidEmptyPassword);
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Assert that the provided cacheEncryptionKey is true.
|
|
150
|
+
*
|
|
151
|
+
* @param cacheEncryptionKey - The cacheEncryptionKey to check.
|
|
152
|
+
* @throws If the cacheEncryptionKey is not true.
|
|
153
|
+
*/
|
|
154
|
+
function assertIsCacheEncryptionKeyTrue(cacheEncryptionKey) {
|
|
155
|
+
if (!cacheEncryptionKey) {
|
|
156
|
+
throw new Error(KeyringControllerError.CacheEncryptionKeyDisabled);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
148
159
|
/**
|
|
149
160
|
* Checks if the provided value is a serialized keyrings array.
|
|
150
161
|
*
|
|
@@ -235,6 +246,7 @@ export class KeyringController extends BaseController {
|
|
|
235
246
|
keyrings: { persist: false, anonymous: false },
|
|
236
247
|
encryptionKey: { persist: false, anonymous: false },
|
|
237
248
|
encryptionSalt: { persist: false, anonymous: false },
|
|
249
|
+
encryptedEncryptionKey: { persist: true, anonymous: false },
|
|
238
250
|
},
|
|
239
251
|
messenger,
|
|
240
252
|
state: {
|
|
@@ -247,17 +259,24 @@ export class KeyringController extends BaseController {
|
|
|
247
259
|
_KeyringController_vaultOperationMutex.set(this, new Mutex());
|
|
248
260
|
_KeyringController_keyringBuilders.set(this, void 0);
|
|
249
261
|
_KeyringController_encryptor.set(this, void 0);
|
|
262
|
+
_KeyringController_cacheEncryptionKey.set(this, void 0);
|
|
250
263
|
_KeyringController_keyrings.set(this, void 0);
|
|
251
264
|
_KeyringController_unsupportedKeyrings.set(this, void 0);
|
|
265
|
+
_KeyringController_password.set(this, void 0);
|
|
252
266
|
_KeyringController_encryptionKey.set(this, void 0);
|
|
253
267
|
_KeyringController_qrKeyringStateListener.set(this, void 0);
|
|
254
268
|
__classPrivateFieldSet(this, _KeyringController_keyringBuilders, keyringBuilders
|
|
255
269
|
? keyringBuilders.concat(defaultKeyringBuilders)
|
|
256
270
|
: defaultKeyringBuilders, "f");
|
|
257
|
-
assertIsExportableKeyEncryptor(encryptor);
|
|
258
271
|
__classPrivateFieldSet(this, _KeyringController_encryptor, encryptor, "f");
|
|
259
272
|
__classPrivateFieldSet(this, _KeyringController_keyrings, [], "f");
|
|
260
273
|
__classPrivateFieldSet(this, _KeyringController_unsupportedKeyrings, [], "f");
|
|
274
|
+
// This option allows the controller to cache an exported key
|
|
275
|
+
// for use in decrypting and encrypting data without password
|
|
276
|
+
__classPrivateFieldSet(this, _KeyringController_cacheEncryptionKey, Boolean(options.cacheEncryptionKey), "f");
|
|
277
|
+
if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
|
|
278
|
+
assertIsExportableKeyEncryptor(encryptor);
|
|
279
|
+
}
|
|
261
280
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_registerMessageHandlers).call(this);
|
|
262
281
|
}
|
|
263
282
|
/**
|
|
@@ -327,9 +346,11 @@ export class KeyringController extends BaseController {
|
|
|
327
346
|
* @param password - Password to unlock keychain.
|
|
328
347
|
* @param seed - A BIP39-compliant seed phrase as Uint8Array,
|
|
329
348
|
* either as a string or an array of UTF-8 bytes that represent the string.
|
|
349
|
+
* @param encryptionKey - Optional encryption key to encrypt the new vault. If
|
|
350
|
+
* set, envelope encryption will be used.
|
|
330
351
|
* @returns Promise resolving when the operation ends successfully.
|
|
331
352
|
*/
|
|
332
|
-
async createNewVaultAndRestore(password, seed) {
|
|
353
|
+
async createNewVaultAndRestore(password, seed, encryptionKey) {
|
|
333
354
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
|
|
334
355
|
assertIsValidPassword(password);
|
|
335
356
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createNewVaultWithKeyring).call(this, password, {
|
|
@@ -338,25 +359,28 @@ export class KeyringController extends BaseController {
|
|
|
338
359
|
mnemonic: seed,
|
|
339
360
|
numberOfAccounts: 1,
|
|
340
361
|
},
|
|
341
|
-
});
|
|
362
|
+
}, encryptionKey);
|
|
342
363
|
});
|
|
343
364
|
}
|
|
344
365
|
/**
|
|
345
366
|
* Create a new vault and primary keyring.
|
|
346
367
|
*
|
|
347
|
-
* This only works if keyrings are empty. If there is a pre-existing unlocked
|
|
348
|
-
* If there is a pre-existing locked
|
|
368
|
+
* This only works if keyrings are empty. If there is a pre-existing unlocked
|
|
369
|
+
* vault, calling this will have no effect. If there is a pre-existing locked
|
|
370
|
+
* vault, it will be replaced.
|
|
349
371
|
*
|
|
350
372
|
* @param password - Password to unlock the new vault.
|
|
373
|
+
* @param encryptionKey - Optional encryption key to encrypt the new vault. If
|
|
374
|
+
* set, envelope encryption will be used.
|
|
351
375
|
* @returns Promise resolving when the operation ends successfully.
|
|
352
376
|
*/
|
|
353
|
-
async createNewVaultAndKeychain(password) {
|
|
377
|
+
async createNewVaultAndKeychain(password, encryptionKey) {
|
|
354
378
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
|
|
355
379
|
const accounts = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getAccountsFromKeyrings).call(this);
|
|
356
380
|
if (!accounts.length) {
|
|
357
381
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createNewVaultWithKeyring).call(this, password, {
|
|
358
382
|
type: KeyringTypes.hd,
|
|
359
|
-
});
|
|
383
|
+
}, encryptionKey);
|
|
360
384
|
}
|
|
361
385
|
});
|
|
362
386
|
}
|
|
@@ -385,7 +409,16 @@ export class KeyringController extends BaseController {
|
|
|
385
409
|
if (!this.state.vault) {
|
|
386
410
|
throw new Error(KeyringControllerError.VaultError);
|
|
387
411
|
}
|
|
388
|
-
|
|
412
|
+
if (this.state.encryptedEncryptionKey) {
|
|
413
|
+
// Envelope encryption mode.
|
|
414
|
+
assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
|
|
415
|
+
const decryptedEncryptionKey = (await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, this.state.encryptedEncryptionKey));
|
|
416
|
+
const importedKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(decryptedEncryptionKey);
|
|
417
|
+
await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(importedKey, this.state.vault);
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, this.state.vault);
|
|
421
|
+
}
|
|
389
422
|
}
|
|
390
423
|
/**
|
|
391
424
|
* Returns the status of the vault.
|
|
@@ -574,7 +607,7 @@ export class KeyringController extends BaseController {
|
|
|
574
607
|
try {
|
|
575
608
|
wallet = importers.fromEtherWallet(input, password);
|
|
576
609
|
}
|
|
577
|
-
catch
|
|
610
|
+
catch {
|
|
578
611
|
wallet = wallet || (await Wallet.fromV3(input, password, true));
|
|
579
612
|
}
|
|
580
613
|
privateKey = bytesToHex(wallet.getPrivateKey());
|
|
@@ -632,6 +665,7 @@ export class KeyringController extends BaseController {
|
|
|
632
665
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
|
|
633
666
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
634
667
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unsubscribeFromQRKeyringsEvents).call(this);
|
|
668
|
+
__classPrivateFieldSet(this, _KeyringController_password, undefined, "f");
|
|
635
669
|
__classPrivateFieldSet(this, _KeyringController_encryptionKey, undefined, "f");
|
|
636
670
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
|
|
637
671
|
this.update((state) => {
|
|
@@ -813,10 +847,33 @@ export class KeyringController extends BaseController {
|
|
|
813
847
|
* @returns Promise resolving when the operation completes.
|
|
814
848
|
*/
|
|
815
849
|
changePassword(password) {
|
|
850
|
+
return this.changePasswordAndEncryptionKey(password);
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
853
|
+
* Changes the password and encryption key used to encrypt the vault.
|
|
854
|
+
*
|
|
855
|
+
* @param password - The new password.
|
|
856
|
+
* @param encryptionKey - The new encryption key. If omitted, the encryption
|
|
857
|
+
* key will not be changed.
|
|
858
|
+
* @returns Promise resolving when the operation completes.
|
|
859
|
+
*/
|
|
860
|
+
changePasswordAndEncryptionKey(password, encryptionKey) {
|
|
816
861
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
|
|
817
862
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
|
|
818
863
|
assertIsValidPassword(password);
|
|
819
|
-
|
|
864
|
+
// Update password.
|
|
865
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
866
|
+
// Update encryption key.
|
|
867
|
+
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateCachedEncryptionKey).call(this, encryptionKey);
|
|
868
|
+
// We need to clear encryption key and salt from state
|
|
869
|
+
// to force the controller to re-encrypt the vault using
|
|
870
|
+
// the new password.
|
|
871
|
+
if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
|
|
872
|
+
this.update((state) => {
|
|
873
|
+
delete state.encryptionKey;
|
|
874
|
+
delete state.encryptionSalt;
|
|
875
|
+
});
|
|
876
|
+
}
|
|
820
877
|
});
|
|
821
878
|
}
|
|
822
879
|
/**
|
|
@@ -824,13 +881,12 @@ export class KeyringController extends BaseController {
|
|
|
824
881
|
* using the given encryption key and salt.
|
|
825
882
|
*
|
|
826
883
|
* @param encryptionKey - Key to unlock the keychain.
|
|
884
|
+
* @param encryptionSalt - Salt to unlock the keychain.
|
|
827
885
|
* @returns Promise resolving when the operation completes.
|
|
828
886
|
*/
|
|
829
|
-
async submitEncryptionKey(encryptionKey) {
|
|
887
|
+
async submitEncryptionKey(encryptionKey, encryptionSalt) {
|
|
830
888
|
const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
831
|
-
const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this,
|
|
832
|
-
exportedEncryptionKey: encryptionKey,
|
|
833
|
-
});
|
|
889
|
+
const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, undefined, encryptionKey, encryptionSalt);
|
|
834
890
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
835
891
|
return result;
|
|
836
892
|
});
|
|
@@ -858,7 +914,7 @@ export class KeyringController extends BaseController {
|
|
|
858
914
|
*/
|
|
859
915
|
async submitPassword(password) {
|
|
860
916
|
const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
861
|
-
const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this,
|
|
917
|
+
const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, password);
|
|
862
918
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
863
919
|
return result;
|
|
864
920
|
});
|
|
@@ -868,12 +924,6 @@ export class KeyringController extends BaseController {
|
|
|
868
924
|
// can attempt to upgrade the vault.
|
|
869
925
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
870
926
|
if (newMetadata || __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isNewEncryptionAvailable).call(this)) {
|
|
871
|
-
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveEncryptionKey).call(this, password, {
|
|
872
|
-
// If the vault is being upgraded, we want to ignore the metadata
|
|
873
|
-
// that is already in the vault, so we can effectively
|
|
874
|
-
// re-encrypt the vault with the new encryption config.
|
|
875
|
-
ignoreVaultKeyMetadata: true,
|
|
876
|
-
});
|
|
877
927
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
|
|
878
928
|
}
|
|
879
929
|
});
|
|
@@ -1127,7 +1177,7 @@ export class KeyringController extends BaseController {
|
|
|
1127
1177
|
});
|
|
1128
1178
|
}
|
|
1129
1179
|
}
|
|
1130
|
-
_KeyringController_controllerOperationMutex = new WeakMap(), _KeyringController_vaultOperationMutex = new WeakMap(), _KeyringController_keyringBuilders = new WeakMap(), _KeyringController_encryptor = new WeakMap(), _KeyringController_keyrings = new WeakMap(), _KeyringController_unsupportedKeyrings = new WeakMap(), _KeyringController_encryptionKey = new WeakMap(), _KeyringController_qrKeyringStateListener = new WeakMap(), _KeyringController_instances = new WeakSet(), _KeyringController_registerMessageHandlers = function _KeyringController_registerMessageHandlers() {
|
|
1180
|
+
_KeyringController_controllerOperationMutex = new WeakMap(), _KeyringController_vaultOperationMutex = new WeakMap(), _KeyringController_keyringBuilders = new WeakMap(), _KeyringController_encryptor = new WeakMap(), _KeyringController_cacheEncryptionKey = new WeakMap(), _KeyringController_keyrings = new WeakMap(), _KeyringController_unsupportedKeyrings = new WeakMap(), _KeyringController_password = new WeakMap(), _KeyringController_encryptionKey = new WeakMap(), _KeyringController_qrKeyringStateListener = new WeakMap(), _KeyringController_instances = new WeakSet(), _KeyringController_registerMessageHandlers = function _KeyringController_registerMessageHandlers() {
|
|
1131
1181
|
this.messagingSystem.registerActionHandler(`${name}:signMessage`, this.signMessage.bind(this));
|
|
1132
1182
|
this.messagingSystem.registerActionHandler(`${name}:signEip7702Authorization`, this.signEip7702Authorization.bind(this));
|
|
1133
1183
|
this.messagingSystem.registerActionHandler(`${name}:signPersonalMessage`, this.signPersonalMessage.bind(this));
|
|
@@ -1196,9 +1246,10 @@ async function _KeyringController_addQRKeyring() {
|
|
|
1196
1246
|
* @param keyring - A object containing the params to instantiate a new keyring.
|
|
1197
1247
|
* @param keyring.type - The keyring type.
|
|
1198
1248
|
* @param keyring.opts - Optional parameters required to instantiate the keyring.
|
|
1249
|
+
* @param encryptionKey - Optional encryption key to encrypt the vault.
|
|
1199
1250
|
* @returns A promise that resolves to the state.
|
|
1200
1251
|
*/
|
|
1201
|
-
async function _KeyringController_createNewVaultWithKeyring(password, keyring) {
|
|
1252
|
+
async function _KeyringController_createNewVaultWithKeyring(password, keyring, encryptionKey) {
|
|
1202
1253
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
|
|
1203
1254
|
if (typeof password !== 'string') {
|
|
1204
1255
|
throw new TypeError(KeyringControllerError.WrongPasswordType);
|
|
@@ -1207,56 +1258,21 @@ async function _KeyringController_createNewVaultWithKeyring(password, keyring) {
|
|
|
1207
1258
|
delete state.encryptionKey;
|
|
1208
1259
|
delete state.encryptionSalt;
|
|
1209
1260
|
});
|
|
1210
|
-
|
|
1261
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
1262
|
+
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateCachedEncryptionKey).call(this, encryptionKey);
|
|
1211
1263
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
|
|
1212
1264
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyringWithFirstAccount).call(this, keyring.type, keyring.opts);
|
|
1213
1265
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
1214
|
-
},
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
* When the controller has a vault in its state, the key is derived
|
|
1221
|
-
* using the salt from the vault. If the vault is empty, a new salt
|
|
1222
|
-
* is generated and used to derive the key.
|
|
1223
|
-
*
|
|
1224
|
-
* @param password - The password to use for decryption or derivation.
|
|
1225
|
-
* @param options - Options for the key derivation.
|
|
1226
|
-
* @param options.ignoreVaultKeyMetadata - Whether to ignore the vault key metadata
|
|
1227
|
-
*/
|
|
1228
|
-
async function _KeyringController_deriveEncryptionKey(password, options = {
|
|
1229
|
-
ignoreVaultKeyMetadata: false,
|
|
1230
|
-
}) {
|
|
1231
|
-
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
|
|
1232
|
-
const { vault } = this.state;
|
|
1233
|
-
if (typeof password !== 'string') {
|
|
1234
|
-
throw new TypeError(KeyringControllerError.WrongPasswordType);
|
|
1235
|
-
}
|
|
1236
|
-
let salt, keyMetadata;
|
|
1237
|
-
if (vault && !options.ignoreVaultKeyMetadata) {
|
|
1238
|
-
const parsedVault = JSON.parse(vault);
|
|
1239
|
-
salt = parsedVault.salt;
|
|
1240
|
-
keyMetadata = parsedVault.keyMetadata;
|
|
1266
|
+
}, _KeyringController_updateCachedEncryptionKey = function _KeyringController_updateCachedEncryptionKey(encryptionKey) {
|
|
1267
|
+
if (!encryptionKey && this.state.encryptedEncryptionKey) {
|
|
1268
|
+
// If no encryption key is provided and we are in envelope encryption
|
|
1269
|
+
// mode, use the cached encryption key. This case occurs when we call
|
|
1270
|
+
// change password without providing a new encryption key.
|
|
1271
|
+
__classPrivateFieldSet(this, _KeyringController_encryptionKey, this.state.encryptionKey, "f");
|
|
1241
1272
|
}
|
|
1242
1273
|
else {
|
|
1243
|
-
|
|
1274
|
+
__classPrivateFieldSet(this, _KeyringController_encryptionKey, encryptionKey, "f");
|
|
1244
1275
|
}
|
|
1245
|
-
const exportedEncryptionKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").exportKey(await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").keyFromPassword(password, salt, true, keyMetadata));
|
|
1246
|
-
__classPrivateFieldSet(this, _KeyringController_encryptionKey, {
|
|
1247
|
-
salt,
|
|
1248
|
-
exported: exportedEncryptionKey,
|
|
1249
|
-
}, "f");
|
|
1250
|
-
}, _KeyringController_useEncryptionKey = function _KeyringController_useEncryptionKey(encryptionKey, encryptionSalt) {
|
|
1251
|
-
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
|
|
1252
|
-
if (typeof encryptionKey !== 'string' ||
|
|
1253
|
-
typeof encryptionSalt !== 'string') {
|
|
1254
|
-
throw new TypeError(KeyringControllerError.WrongEncryptionKeyType);
|
|
1255
|
-
}
|
|
1256
|
-
__classPrivateFieldSet(this, _KeyringController_encryptionKey, {
|
|
1257
|
-
salt: encryptionSalt,
|
|
1258
|
-
exported: encryptionKey,
|
|
1259
|
-
}, "f");
|
|
1260
1276
|
}, _KeyringController_verifySeedPhrase =
|
|
1261
1277
|
/**
|
|
1262
1278
|
* Internal non-exclusive method to verify the seed phrase.
|
|
@@ -1345,6 +1361,7 @@ async function _KeyringController_getSerializedKeyrings({ includeUnsupported } =
|
|
|
1345
1361
|
async function _KeyringController_getSessionState() {
|
|
1346
1362
|
return {
|
|
1347
1363
|
keyrings: await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this),
|
|
1364
|
+
password: __classPrivateFieldGet(this, _KeyringController_password, "f"),
|
|
1348
1365
|
encryptionKey: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f"),
|
|
1349
1366
|
};
|
|
1350
1367
|
}, _KeyringController_restoreSerializedKeyrings =
|
|
@@ -1374,28 +1391,63 @@ async function _KeyringController_restoreSerializedKeyrings(serializedKeyrings)
|
|
|
1374
1391
|
* Unlock Keyrings, decrypting the vault and deserializing all
|
|
1375
1392
|
* keyrings contained in it, using a password or an encryption key with salt.
|
|
1376
1393
|
*
|
|
1377
|
-
* @param
|
|
1394
|
+
* @param password - The keyring controller password.
|
|
1395
|
+
* @param encryptionKey - An exported key string to unlock keyrings with.
|
|
1396
|
+
* @param encryptionSalt - The salt used to encrypt the vault.
|
|
1378
1397
|
* @returns A promise resolving to the deserialized keyrings array.
|
|
1379
1398
|
*/
|
|
1380
|
-
async function _KeyringController_unlockKeyrings(
|
|
1399
|
+
async function _KeyringController_unlockKeyrings(password, encryptionKey, encryptionSalt) {
|
|
1381
1400
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
|
|
1382
|
-
|
|
1401
|
+
const { vault: encryptedVault, encryptedEncryptionKey } = this.state;
|
|
1402
|
+
if (!encryptedVault) {
|
|
1383
1403
|
throw new Error(KeyringControllerError.VaultError);
|
|
1384
1404
|
}
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1405
|
+
let vault;
|
|
1406
|
+
const updatedState = {};
|
|
1407
|
+
if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
|
|
1408
|
+
assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
|
|
1409
|
+
if (password) {
|
|
1410
|
+
if (encryptedEncryptionKey) {
|
|
1411
|
+
const decryptedEncryptionKey = (await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, encryptedEncryptionKey));
|
|
1412
|
+
const importedKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(decryptedEncryptionKey);
|
|
1413
|
+
vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(importedKey, encryptedVault);
|
|
1414
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
1415
|
+
updatedState.encryptionKey = decryptedEncryptionKey;
|
|
1416
|
+
}
|
|
1417
|
+
else {
|
|
1418
|
+
const result = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithDetail(password, encryptedVault);
|
|
1419
|
+
vault = result.vault;
|
|
1420
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
1421
|
+
updatedState.encryptionKey = result.exportedKeyString;
|
|
1422
|
+
updatedState.encryptionSalt = result.salt;
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
else {
|
|
1426
|
+
const parsedEncryptedVault = JSON.parse(encryptedVault);
|
|
1427
|
+
if (encryptionSalt !== parsedEncryptedVault.salt) {
|
|
1428
|
+
throw new Error(KeyringControllerError.ExpiredCredentials);
|
|
1429
|
+
}
|
|
1430
|
+
if (typeof encryptionKey !== 'string') {
|
|
1431
|
+
throw new TypeError(KeyringControllerError.WrongPasswordType);
|
|
1432
|
+
}
|
|
1433
|
+
const importedKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
|
|
1434
|
+
vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(importedKey, parsedEncryptedVault);
|
|
1435
|
+
// This call is required on the first call because encryptionKey
|
|
1436
|
+
// is not yet inside the memStore
|
|
1437
|
+
updatedState.encryptionKey = encryptionKey;
|
|
1438
|
+
// we can safely assume that encryptionSalt is defined here
|
|
1439
|
+
// because we compare it with the salt from the vault
|
|
1440
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1441
|
+
updatedState.encryptionSalt = encryptionSalt;
|
|
1442
|
+
}
|
|
1388
1443
|
}
|
|
1389
1444
|
else {
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
throw new Error(KeyringControllerError.MissingCredentials);
|
|
1445
|
+
if (typeof password !== 'string') {
|
|
1446
|
+
throw new TypeError(KeyringControllerError.WrongPasswordType);
|
|
1447
|
+
}
|
|
1448
|
+
vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, encryptedVault);
|
|
1449
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
1396
1450
|
}
|
|
1397
|
-
const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
|
|
1398
|
-
const vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(key, parsedEncryptedVault);
|
|
1399
1451
|
if (!isSerializedKeyringsArray(vault)) {
|
|
1400
1452
|
throw new Error(KeyringControllerError.VaultDataError);
|
|
1401
1453
|
}
|
|
@@ -1403,8 +1455,10 @@ async function _KeyringController_unlockKeyrings(credentials) {
|
|
|
1403
1455
|
const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
|
|
1404
1456
|
this.update((state) => {
|
|
1405
1457
|
state.keyrings = updatedKeyrings;
|
|
1406
|
-
|
|
1407
|
-
|
|
1458
|
+
if (updatedState.encryptionKey || updatedState.encryptionSalt) {
|
|
1459
|
+
state.encryptionKey = updatedState.encryptionKey;
|
|
1460
|
+
state.encryptionSalt = updatedState.encryptionSalt;
|
|
1461
|
+
}
|
|
1408
1462
|
});
|
|
1409
1463
|
return { keyrings, newMetadata };
|
|
1410
1464
|
});
|
|
@@ -1412,41 +1466,84 @@ async function _KeyringController_unlockKeyrings(credentials) {
|
|
|
1412
1466
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
|
|
1413
1467
|
// Ensure no duplicate accounts are persisted.
|
|
1414
1468
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoDuplicateAccounts).call(this);
|
|
1415
|
-
|
|
1469
|
+
const { encryptionKey, encryptionSalt, vault } = this.state;
|
|
1470
|
+
// READ THIS CAREFULLY:
|
|
1471
|
+
// We do check if the vault is still considered up-to-date, if not, we would not re-use the
|
|
1472
|
+
// cached key and we will re-generate a new one (based on the password).
|
|
1473
|
+
//
|
|
1474
|
+
// This helps doing seamless updates of the vault. Useful in case we change some cryptographic
|
|
1475
|
+
// parameters to the KDF.
|
|
1476
|
+
const useCachedKey = encryptionKey && vault && __classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated?.(vault);
|
|
1477
|
+
if (!__classPrivateFieldGet(this, _KeyringController_password, "f") && !encryptionKey) {
|
|
1416
1478
|
throw new Error(KeyringControllerError.MissingCredentials);
|
|
1417
1479
|
}
|
|
1418
1480
|
const serializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
|
|
1419
1481
|
if (!serializedKeyrings.some((keyring) => keyring.type === KeyringTypes.hd)) {
|
|
1420
1482
|
throw new Error(KeyringControllerError.NoHdKeyring);
|
|
1421
1483
|
}
|
|
1422
|
-
const
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1484
|
+
const updatedState = {};
|
|
1485
|
+
if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
|
|
1486
|
+
assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
|
|
1487
|
+
if (useCachedKey) {
|
|
1488
|
+
const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
|
|
1489
|
+
const vaultJSON = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithKey(key, serializedKeyrings);
|
|
1490
|
+
vaultJSON.salt = encryptionSalt;
|
|
1491
|
+
updatedState.vault = JSON.stringify(vaultJSON);
|
|
1492
|
+
}
|
|
1493
|
+
else if (__classPrivateFieldGet(this, _KeyringController_password, "f")) {
|
|
1494
|
+
if (__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")) {
|
|
1495
|
+
// Update cached key.
|
|
1496
|
+
updatedState.encryptionKey = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f");
|
|
1497
|
+
// Encrypt key and update encrypted key.
|
|
1498
|
+
const encryptedEncryptionKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encrypt(__classPrivateFieldGet(this, _KeyringController_password, "f"), __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f"));
|
|
1499
|
+
updatedState.encryptedEncryptionKey = encryptedEncryptionKey;
|
|
1500
|
+
// Encrypt and update vault.
|
|
1501
|
+
const importedKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f"));
|
|
1502
|
+
const vaultJSON = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithKey(importedKey, serializedKeyrings);
|
|
1503
|
+
// Note that we don't need to explicitly append the salt to the
|
|
1504
|
+
// vault here as it's already stored as part of the encrypted
|
|
1505
|
+
// encryption key.
|
|
1506
|
+
updatedState.vault = JSON.stringify(vaultJSON);
|
|
1507
|
+
}
|
|
1508
|
+
else {
|
|
1509
|
+
const { vault: newVault, exportedKeyString } = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithDetail(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
|
|
1510
|
+
updatedState.vault = newVault;
|
|
1511
|
+
updatedState.encryptionKey = exportedKeyString;
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
else {
|
|
1516
|
+
assertIsValidPassword(__classPrivateFieldGet(this, _KeyringController_password, "f"));
|
|
1517
|
+
updatedState.vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encrypt(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
|
|
1518
|
+
}
|
|
1519
|
+
if (__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isEnvelopeEncryptionEnabled).call(this)) {
|
|
1520
|
+
assertIsCacheEncryptionKeyTrue(__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f"));
|
|
1521
|
+
}
|
|
1522
|
+
if (!updatedState.vault) {
|
|
1523
|
+
throw new Error(KeyringControllerError.MissingVaultData);
|
|
1429
1524
|
}
|
|
1430
|
-
const updatedState = {
|
|
1431
|
-
vault: JSON.stringify(encryptedVault),
|
|
1432
|
-
encryptionKey: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").exported,
|
|
1433
|
-
encryptionSalt: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").salt,
|
|
1434
|
-
};
|
|
1435
1525
|
const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
|
|
1436
1526
|
this.update((state) => {
|
|
1437
1527
|
state.vault = updatedState.vault;
|
|
1438
1528
|
state.keyrings = updatedKeyrings;
|
|
1439
|
-
|
|
1440
|
-
|
|
1529
|
+
if (updatedState.encryptionKey) {
|
|
1530
|
+
state.encryptionKey = updatedState.encryptionKey;
|
|
1531
|
+
state.encryptionSalt = JSON.parse(updatedState.vault).salt;
|
|
1532
|
+
}
|
|
1533
|
+
if (updatedState.encryptedEncryptionKey) {
|
|
1534
|
+
state.encryptedEncryptionKey = updatedState.encryptedEncryptionKey;
|
|
1535
|
+
}
|
|
1441
1536
|
});
|
|
1442
1537
|
return true;
|
|
1443
1538
|
});
|
|
1444
1539
|
}, _KeyringController_isNewEncryptionAvailable = function _KeyringController_isNewEncryptionAvailable() {
|
|
1445
1540
|
const { vault } = this.state;
|
|
1446
|
-
if (!vault || !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated) {
|
|
1541
|
+
if (!vault || !__classPrivateFieldGet(this, _KeyringController_password, "f") || !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated) {
|
|
1447
1542
|
return false;
|
|
1448
1543
|
}
|
|
1449
1544
|
return !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated(vault);
|
|
1545
|
+
}, _KeyringController_isEnvelopeEncryptionEnabled = function _KeyringController_isEnvelopeEncryptionEnabled() {
|
|
1546
|
+
return this.state.encryptedEncryptionKey || __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f");
|
|
1450
1547
|
}, _KeyringController_getAccountsFromKeyrings =
|
|
1451
1548
|
/**
|
|
1452
1549
|
* Retrieves all the accounts from keyrings instances
|
|
@@ -1531,7 +1628,8 @@ async function _KeyringController_createKeyring(type, data) {
|
|
|
1531
1628
|
if (keyring.init) {
|
|
1532
1629
|
await keyring.init();
|
|
1533
1630
|
}
|
|
1534
|
-
if (type === KeyringTypes.hd &&
|
|
1631
|
+
if (type === KeyringTypes.hd &&
|
|
1632
|
+
(!isObject(data) || !data.mnemonic)) {
|
|
1535
1633
|
if (!keyring.generateRandomMnemonic) {
|
|
1536
1634
|
throw new Error(KeyringControllerError.UnsupportedGenerateRandomMnemonic);
|
|
1537
1635
|
}
|
|
@@ -1653,11 +1751,16 @@ async function _KeyringController_assertNoDuplicateAccounts(additionalKeyrings =
|
|
|
1653
1751
|
}
|
|
1654
1752
|
}, _KeyringController_persistOrRollback =
|
|
1655
1753
|
/**
|
|
1656
|
-
* Execute the given function after acquiring the controller lock
|
|
1657
|
-
*
|
|
1658
|
-
*
|
|
1754
|
+
* Execute the given function after acquiring the controller lock and save the
|
|
1755
|
+
* vault to state after it (only if needed), or rollback to their previous
|
|
1756
|
+
* state in case of error.
|
|
1757
|
+
*
|
|
1758
|
+
* ATTENTION: The callback must **not** alter `controller.state`. Any state
|
|
1759
|
+
* change performed by the callback will not be rolled back on error.
|
|
1659
1760
|
*
|
|
1660
|
-
* @param callback - The function to execute.
|
|
1761
|
+
* @param callback - The function to execute. This callback must **not** alter
|
|
1762
|
+
* `controller.state`. Any state change performed by the callback will not be
|
|
1763
|
+
* rolled back on error.
|
|
1661
1764
|
* @returns The result of the function.
|
|
1662
1765
|
*/
|
|
1663
1766
|
async function _KeyringController_persistOrRollback(callback) {
|
|
@@ -1682,16 +1785,15 @@ async function _KeyringController_persistOrRollback(callback) {
|
|
|
1682
1785
|
async function _KeyringController_withRollback(callback) {
|
|
1683
1786
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async ({ releaseLock }) => {
|
|
1684
1787
|
const currentSerializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
|
|
1685
|
-
const
|
|
1686
|
-
const
|
|
1788
|
+
const currentPassword = __classPrivateFieldGet(this, _KeyringController_password, "f");
|
|
1789
|
+
const currentEncryptionKey = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f");
|
|
1687
1790
|
try {
|
|
1688
1791
|
return await callback({ releaseLock });
|
|
1689
1792
|
}
|
|
1690
1793
|
catch (e) {
|
|
1691
|
-
//
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
}
|
|
1794
|
+
// Previous state is restored.
|
|
1795
|
+
__classPrivateFieldSet(this, _KeyringController_password, currentPassword, "f");
|
|
1796
|
+
__classPrivateFieldSet(this, _KeyringController_encryptionKey, currentEncryptionKey, "f");
|
|
1695
1797
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, currentSerializedKeyrings);
|
|
1696
1798
|
throw e;
|
|
1697
1799
|
}
|