@metamask-previews/keyring-controller 22.1.0-preview-9dd79ac6 → 22.1.0-preview-7b919d75

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 CHANGED
@@ -7,12 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Added
11
+
12
+ - Added optional `SupportedKeyDerivationOptions` type parameter to the `ExportableKeyEncryptor` type ([#5963](https://github.com/MetaMask/core/pull/5963))
13
+ - This type parameter allows specifying the key derivation options supported by the injected encryptor.
14
+
10
15
  ### Changed
11
16
 
17
+ - **BREAKING:** The `KeyringController` constructor now requires an encryptor supporting the `keyFromPassword`, `exportKey` and `generateSalt` methods ([#5963](https://github.com/MetaMask/core/pull/5963))
12
18
  - Bump `@metamask/keyring-api` from `^18.0.0` to `^19.0.0` ([#6146](https://github.com/MetaMask/core/pull/6146))
13
19
  - Bump `@metamask/keyring-internal-api` from `^6.2.0` to `^7.0.0` ([#6146](https://github.com/MetaMask/core/pull/6146))
14
20
  - Bump `@metamask/utils` from `^11.2.0` to `^11.4.2` ([#6054](https://github.com/MetaMask/core/pull/6054))
15
21
 
22
+ ### Removed
23
+
24
+ - **BREAKING:** The `cacheEncryptionKey` parameter has been removed from the `KeyringController` constructor options ([#5963](https://github.com/MetaMask/core/pull/5963))
25
+ - This parameter was previously used to enable encryption key in-memory caching, but it is no longer needed as the controller now always uses the latest encryption key.
26
+ - **BREAKING:** The `submitEncryptionKey` method does not accept an `encryptionSalt` argument anymore ([#5963](https://github.com/MetaMask/core/pull/5963))
27
+ - The encryption salt is now always taken from the vault.
28
+
16
29
  ## [22.1.0]
17
30
 
18
31
  ### Added
@@ -36,7 +36,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
36
36
  var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  return (mod && mod.__esModule) ? mod : { "default": mod };
38
38
  };
39
- var _KeyringController_instances, _KeyringController_controllerOperationMutex, _KeyringController_vaultOperationMutex, _KeyringController_keyringBuilders, _KeyringController_encryptor, _KeyringController_cacheEncryptionKey, _KeyringController_keyrings, _KeyringController_unsupportedKeyrings, _KeyringController_password, _KeyringController_qrKeyringStateListener, _KeyringController_registerMessageHandlers, _KeyringController_getKeyringById, _KeyringController_getKeyringByIdOrDefault, _KeyringController_getKeyringMetadata, _KeyringController_getKeyringBuilderForType, _KeyringController_addQRKeyring, _KeyringController_subscribeToQRKeyringEvents, _KeyringController_unsubscribeFromQRKeyringsEvents, _KeyringController_createNewVaultWithKeyring, _KeyringController_verifySeedPhrase, _KeyringController_getUpdatedKeyrings, _KeyringController_getSerializedKeyrings, _KeyringController_getSessionState, _KeyringController_restoreSerializedKeyrings, _KeyringController_unlockKeyrings, _KeyringController_updateVault, _KeyringController_isNewEncryptionAvailable, _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;
39
+ 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, _KeyringController_deriveEncryptionKey, _KeyringController_useEncryptionKey, _KeyringController_verifySeedPhrase, _KeyringController_getUpdatedKeyrings, _KeyringController_getSerializedKeyrings, _KeyringController_getSessionState, _KeyringController_restoreSerializedKeyrings, _KeyringController_unlockKeyrings, _KeyringController_updateVault, _KeyringController_isNewEncryptionAvailable, _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;
40
40
  Object.defineProperty(exports, "__esModule", { value: true });
41
41
  exports.KeyringController = exports.getDefaultKeyringState = exports.keyringBuilderFactory = exports.SignTypedDataVersion = exports.AccountImportStrategy = exports.isCustodyKeyring = exports.KeyringTypes = void 0;
42
42
  const util_1 = require("@ethereumjs/util");
@@ -255,7 +255,6 @@ class KeyringController extends base_controller_1.BaseController {
255
255
  * @param options - Initial options used to configure this controller
256
256
  * @param options.encryptor - An optional object for defining encryption schemes.
257
257
  * @param options.keyringBuilders - Set a new name for account.
258
- * @param options.cacheEncryptionKey - Whether to cache or not encryption key.
259
258
  * @param options.messenger - A restricted messenger.
260
259
  * @param options.state - Initial state to set on this controller.
261
260
  */
@@ -281,23 +280,17 @@ class KeyringController extends base_controller_1.BaseController {
281
280
  _KeyringController_vaultOperationMutex.set(this, new async_mutex_1.Mutex());
282
281
  _KeyringController_keyringBuilders.set(this, void 0);
283
282
  _KeyringController_encryptor.set(this, void 0);
284
- _KeyringController_cacheEncryptionKey.set(this, void 0);
285
283
  _KeyringController_keyrings.set(this, void 0);
286
284
  _KeyringController_unsupportedKeyrings.set(this, void 0);
287
- _KeyringController_password.set(this, void 0);
285
+ _KeyringController_encryptionKey.set(this, void 0);
288
286
  _KeyringController_qrKeyringStateListener.set(this, void 0);
289
287
  __classPrivateFieldSet(this, _KeyringController_keyringBuilders, keyringBuilders
290
288
  ? keyringBuilders.concat(defaultKeyringBuilders)
291
289
  : defaultKeyringBuilders, "f");
290
+ assertIsExportableKeyEncryptor(encryptor);
292
291
  __classPrivateFieldSet(this, _KeyringController_encryptor, encryptor, "f");
293
292
  __classPrivateFieldSet(this, _KeyringController_keyrings, [], "f");
294
293
  __classPrivateFieldSet(this, _KeyringController_unsupportedKeyrings, [], "f");
295
- // This option allows the controller to cache an exported key
296
- // for use in decrypting and encrypting data without password
297
- __classPrivateFieldSet(this, _KeyringController_cacheEncryptionKey, Boolean(options.cacheEncryptionKey), "f");
298
- if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
299
- assertIsExportableKeyEncryptor(encryptor);
300
- }
301
294
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_registerMessageHandlers).call(this);
302
295
  }
303
296
  /**
@@ -672,7 +665,7 @@ class KeyringController extends base_controller_1.BaseController {
672
665
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
673
666
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
674
667
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unsubscribeFromQRKeyringsEvents).call(this);
675
- __classPrivateFieldSet(this, _KeyringController_password, undefined, "f");
668
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, undefined, "f");
676
669
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
677
670
  this.update((state) => {
678
671
  state.isUnlocked = false;
@@ -854,22 +847,9 @@ class KeyringController extends base_controller_1.BaseController {
854
847
  */
855
848
  changePassword(password) {
856
849
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
857
- // If the password is the same, do nothing.
858
- if (__classPrivateFieldGet(this, _KeyringController_password, "f") === password) {
859
- return Promise.resolve();
860
- }
861
850
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
862
851
  assertIsValidPassword(password);
863
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
864
- // We need to clear encryption key and salt from state
865
- // to force the controller to re-encrypt the vault using
866
- // the new password.
867
- if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
868
- this.update((state) => {
869
- delete state.encryptionKey;
870
- delete state.encryptionSalt;
871
- });
872
- }
852
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveEncryptionKey).call(this, password);
873
853
  });
874
854
  }
875
855
  /**
@@ -883,7 +863,10 @@ class KeyringController extends base_controller_1.BaseController {
883
863
  */
884
864
  async submitEncryptionKey(encryptionKey, encryptionSalt) {
885
865
  const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
886
- const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, undefined, encryptionKey, encryptionSalt);
866
+ const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, {
867
+ exportedEncryptionKey: encryptionKey,
868
+ encryptionKeySalt: encryptionSalt,
869
+ });
887
870
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
888
871
  return result;
889
872
  });
@@ -910,9 +893,8 @@ class KeyringController extends base_controller_1.BaseController {
910
893
  async exportEncryptionKey() {
911
894
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
912
895
  return await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async () => {
913
- const { encryptionKey } = this.state;
914
- assertIsEncryptionKeySet(encryptionKey);
915
- return encryptionKey;
896
+ assertIsEncryptionKeySet(__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")?.exported);
897
+ return __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").exported;
916
898
  });
917
899
  }
918
900
  /**
@@ -924,7 +906,7 @@ class KeyringController extends base_controller_1.BaseController {
924
906
  */
925
907
  async submitPassword(password) {
926
908
  const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
927
- const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, password);
909
+ const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, { password });
928
910
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
929
911
  return result;
930
912
  });
@@ -934,6 +916,12 @@ class KeyringController extends base_controller_1.BaseController {
934
916
  // can attempt to upgrade the vault.
935
917
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
936
918
  if (newMetadata || __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isNewEncryptionAvailable).call(this)) {
919
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveEncryptionKey).call(this, password, {
920
+ // If the vault is being upgraded, we want to ignore the metadata
921
+ // that is already in the vault, so we can effectively
922
+ // re-encrypt the vault with the new encryption config.
923
+ useVaultKeyMetadata: false,
924
+ });
937
925
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
938
926
  }
939
927
  });
@@ -1188,7 +1176,7 @@ class KeyringController extends base_controller_1.BaseController {
1188
1176
  }
1189
1177
  }
1190
1178
  exports.KeyringController = KeyringController;
1191
- _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_qrKeyringStateListener = new WeakMap(), _KeyringController_instances = new WeakSet(), _KeyringController_registerMessageHandlers = function _KeyringController_registerMessageHandlers() {
1179
+ _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() {
1192
1180
  this.messagingSystem.registerActionHandler(`${name}:signMessage`, this.signMessage.bind(this));
1193
1181
  this.messagingSystem.registerActionHandler(`${name}:signEip7702Authorization`, this.signEip7702Authorization.bind(this));
1194
1182
  this.messagingSystem.registerActionHandler(`${name}:signPersonalMessage`, this.signPersonalMessage.bind(this));
@@ -1268,10 +1256,60 @@ async function _KeyringController_createNewVaultWithKeyring(password, keyring) {
1268
1256
  delete state.encryptionKey;
1269
1257
  delete state.encryptionSalt;
1270
1258
  });
1271
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1259
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveEncryptionKey).call(this, password);
1272
1260
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
1273
1261
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyringWithFirstAccount).call(this, keyring.type, keyring.opts);
1274
1262
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
1263
+ }, _KeyringController_deriveEncryptionKey =
1264
+ /**
1265
+ * Derive the vault encryption key from the provided password, and
1266
+ * assign it to the instance variable for later use with cryptographic
1267
+ * functions.
1268
+ *
1269
+ * When the controller has a vault in its state, the key is derived
1270
+ * using the salt from the vault. If the vault is empty, a new salt
1271
+ * is generated and used to derive the key.
1272
+ *
1273
+ * @param password - The password to use for decryption or derivation.
1274
+ * @param options - Options for the key derivation.
1275
+ * @param options.useVaultKeyMetadata - Whether to use the vault key metadata
1276
+ */
1277
+ async function _KeyringController_deriveEncryptionKey(password, options = {
1278
+ useVaultKeyMetadata: true,
1279
+ }) {
1280
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1281
+ const { vault } = this.state;
1282
+ if (typeof password !== 'string') {
1283
+ throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
1284
+ }
1285
+ let salt, keyMetadata;
1286
+ if (vault && options.useVaultKeyMetadata) {
1287
+ const parsedVault = JSON.parse(vault);
1288
+ salt = parsedVault.salt;
1289
+ keyMetadata = parsedVault.keyMetadata;
1290
+ }
1291
+ else {
1292
+ salt = __classPrivateFieldGet(this, _KeyringController_encryptor, "f").generateSalt();
1293
+ }
1294
+ const exportedEncryptionKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").exportKey(await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").keyFromPassword(password, salt, true, keyMetadata));
1295
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, {
1296
+ salt,
1297
+ exported: exportedEncryptionKey,
1298
+ }, "f");
1299
+ }, _KeyringController_useEncryptionKey = function _KeyringController_useEncryptionKey(encryptionKey, encryptionSalt) {
1300
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1301
+ if (typeof encryptionKey !== 'string' ||
1302
+ typeof encryptionSalt !== 'string') {
1303
+ throw new TypeError(constants_1.KeyringControllerError.WrongEncryptionKeyType);
1304
+ }
1305
+ const { vault } = this.state;
1306
+ if (vault && JSON.parse(vault).salt !== encryptionSalt) {
1307
+ throw new Error(constants_1.KeyringControllerError.ExpiredCredentials);
1308
+ }
1309
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, {
1310
+ salt: encryptionSalt,
1311
+ exported: encryptionKey,
1312
+ }, "f");
1275
1313
  }, _KeyringController_verifySeedPhrase =
1276
1314
  /**
1277
1315
  * Internal non-exclusive method to verify the seed phrase.
@@ -1352,7 +1390,7 @@ async function _KeyringController_getSerializedKeyrings({ includeUnsupported } =
1352
1390
  return serializedKeyrings;
1353
1391
  }, _KeyringController_getSessionState =
1354
1392
  /**
1355
- * Get a snapshot of session data held by class variables.
1393
+ * Get a snapshot of session data held by instance variables.
1356
1394
  *
1357
1395
  * @returns An object with serialized keyrings, keyrings metadata,
1358
1396
  * and the user password.
@@ -1360,7 +1398,7 @@ async function _KeyringController_getSerializedKeyrings({ includeUnsupported } =
1360
1398
  async function _KeyringController_getSessionState() {
1361
1399
  return {
1362
1400
  keyrings: await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this),
1363
- password: __classPrivateFieldGet(this, _KeyringController_password, "f"),
1401
+ encryptionKey: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f"),
1364
1402
  };
1365
1403
  }, _KeyringController_restoreSerializedKeyrings =
1366
1404
  /**
@@ -1389,54 +1427,27 @@ async function _KeyringController_restoreSerializedKeyrings(serializedKeyrings)
1389
1427
  * Unlock Keyrings, decrypting the vault and deserializing all
1390
1428
  * keyrings contained in it, using a password or an encryption key with salt.
1391
1429
  *
1392
- * @param password - The keyring controller password.
1393
- * @param encryptionKey - An exported key string to unlock keyrings with.
1394
- * @param encryptionSalt - The salt used to encrypt the vault.
1430
+ * @param credentials - The credentials to unlock the keyrings.
1395
1431
  * @returns A promise resolving to the deserialized keyrings array.
1396
1432
  */
1397
- async function _KeyringController_unlockKeyrings(password, encryptionKey, encryptionSalt) {
1433
+ async function _KeyringController_unlockKeyrings(credentials) {
1398
1434
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
1399
- const encryptedVault = this.state.vault;
1400
- if (!encryptedVault) {
1435
+ if (!this.state.vault) {
1401
1436
  throw new Error(constants_1.KeyringControllerError.VaultError);
1402
1437
  }
1403
- let vault;
1404
- const updatedState = {};
1405
- if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
1406
- assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
1407
- if (password) {
1408
- const result = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithDetail(password, encryptedVault);
1409
- vault = result.vault;
1410
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1411
- updatedState.encryptionKey = result.exportedKeyString;
1412
- updatedState.encryptionSalt = result.salt;
1413
- }
1414
- else {
1415
- const parsedEncryptedVault = JSON.parse(encryptedVault);
1416
- if (encryptionSalt && encryptionSalt !== parsedEncryptedVault.salt) {
1417
- throw new Error(constants_1.KeyringControllerError.ExpiredCredentials);
1418
- }
1419
- else {
1420
- encryptionSalt = parsedEncryptedVault.salt;
1421
- }
1422
- if (typeof encryptionKey !== 'string') {
1423
- throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
1424
- }
1425
- const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
1426
- vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(key, parsedEncryptedVault);
1427
- // This call is required on the first call because encryptionKey
1428
- // is not yet inside the memStore
1429
- updatedState.encryptionKey = encryptionKey;
1430
- updatedState.encryptionSalt = encryptionSalt;
1431
- }
1438
+ const parsedEncryptedVault = JSON.parse(this.state.vault);
1439
+ if ('password' in credentials) {
1440
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveEncryptionKey).call(this, credentials.password);
1432
1441
  }
1433
1442
  else {
1434
- if (typeof password !== 'string') {
1435
- throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
1436
- }
1437
- vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, encryptedVault);
1438
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1443
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_useEncryptionKey).call(this, credentials.exportedEncryptionKey, credentials.encryptionKeySalt || parsedEncryptedVault.salt);
1444
+ }
1445
+ const encryptionKey = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")?.exported;
1446
+ if (!encryptionKey) {
1447
+ throw new Error(constants_1.KeyringControllerError.MissingCredentials);
1439
1448
  }
1449
+ const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
1450
+ const vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(key, parsedEncryptedVault);
1440
1451
  if (!isSerializedKeyringsArray(vault)) {
1441
1452
  throw new Error(constants_1.KeyringControllerError.VaultDataError);
1442
1453
  }
@@ -1444,10 +1455,8 @@ async function _KeyringController_unlockKeyrings(password, encryptionKey, encryp
1444
1455
  const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
1445
1456
  this.update((state) => {
1446
1457
  state.keyrings = updatedKeyrings;
1447
- if (updatedState.encryptionKey || updatedState.encryptionSalt) {
1448
- state.encryptionKey = updatedState.encryptionKey;
1449
- state.encryptionSalt = updatedState.encryptionSalt;
1450
- }
1458
+ state.encryptionKey = encryptionKey;
1459
+ state.encryptionSalt = parsedEncryptedVault.salt;
1451
1460
  });
1452
1461
  return { keyrings, newMetadata };
1453
1462
  });
@@ -1455,57 +1464,36 @@ async function _KeyringController_unlockKeyrings(password, encryptionKey, encryp
1455
1464
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
1456
1465
  // Ensure no duplicate accounts are persisted.
1457
1466
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoDuplicateAccounts).call(this);
1458
- const { encryptionKey, encryptionSalt, vault } = this.state;
1459
- // READ THIS CAREFULLY:
1460
- // We do check if the vault is still considered up-to-date, if not, we would not re-use the
1461
- // cached key and we will re-generate a new one (based on the password).
1462
- //
1463
- // This helps doing seamless updates of the vault. Useful in case we change some cryptographic
1464
- // parameters to the KDF.
1465
- const useCachedKey = encryptionKey && vault && __classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated?.(vault);
1466
- if (!__classPrivateFieldGet(this, _KeyringController_password, "f") && !encryptionKey) {
1467
+ if (!__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")) {
1467
1468
  throw new Error(constants_1.KeyringControllerError.MissingCredentials);
1468
1469
  }
1469
1470
  const serializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
1470
1471
  if (!serializedKeyrings.some((keyring) => keyring.type === KeyringTypes.hd)) {
1471
1472
  throw new Error(constants_1.KeyringControllerError.NoHdKeyring);
1472
1473
  }
1473
- const updatedState = {};
1474
- if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
1475
- assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
1476
- if (useCachedKey) {
1477
- const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
1478
- const vaultJSON = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithKey(key, serializedKeyrings);
1479
- vaultJSON.salt = encryptionSalt;
1480
- updatedState.vault = JSON.stringify(vaultJSON);
1481
- }
1482
- else if (__classPrivateFieldGet(this, _KeyringController_password, "f")) {
1483
- const { vault: newVault, exportedKeyString } = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithDetail(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
1484
- updatedState.vault = newVault;
1485
- updatedState.encryptionKey = exportedKeyString;
1486
- }
1487
- }
1488
- else {
1489
- assertIsValidPassword(__classPrivateFieldGet(this, _KeyringController_password, "f"));
1490
- updatedState.vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encrypt(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
1491
- }
1492
- if (!updatedState.vault) {
1493
- throw new Error(constants_1.KeyringControllerError.MissingVaultData);
1494
- }
1474
+ const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").exported);
1475
+ const encryptedVault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithKey(key, serializedKeyrings);
1476
+ // We need to include the salt used to derive
1477
+ // the encryption key, to be able to derive it
1478
+ // from password again.
1479
+ encryptedVault.salt = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").salt;
1480
+ const updatedState = {
1481
+ vault: JSON.stringify(encryptedVault),
1482
+ encryptionKey: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").exported,
1483
+ encryptionSalt: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").salt,
1484
+ };
1495
1485
  const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
1496
1486
  this.update((state) => {
1497
1487
  state.vault = updatedState.vault;
1498
1488
  state.keyrings = updatedKeyrings;
1499
- if (updatedState.encryptionKey) {
1500
- state.encryptionKey = updatedState.encryptionKey;
1501
- state.encryptionSalt = JSON.parse(updatedState.vault).salt;
1502
- }
1489
+ state.encryptionKey = updatedState.encryptionKey;
1490
+ state.encryptionSalt = updatedState.encryptionSalt;
1503
1491
  });
1504
1492
  return true;
1505
1493
  });
1506
1494
  }, _KeyringController_isNewEncryptionAvailable = function _KeyringController_isNewEncryptionAvailable() {
1507
1495
  const { vault } = this.state;
1508
- if (!vault || !__classPrivateFieldGet(this, _KeyringController_password, "f") || !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated) {
1496
+ if (!vault || !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated) {
1509
1497
  return false;
1510
1498
  }
1511
1499
  return !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated(vault);
@@ -1744,13 +1732,13 @@ async function _KeyringController_persistOrRollback(callback) {
1744
1732
  async function _KeyringController_withRollback(callback) {
1745
1733
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async ({ releaseLock }) => {
1746
1734
  const currentSerializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
1747
- const currentPassword = __classPrivateFieldGet(this, _KeyringController_password, "f");
1735
+ const currentEncryptionKey = (0, lodash_1.cloneDeep)(__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f"));
1748
1736
  try {
1749
1737
  return await callback({ releaseLock });
1750
1738
  }
1751
1739
  catch (e) {
1752
- // Keyrings and password are restored to their previous state
1753
- __classPrivateFieldSet(this, _KeyringController_password, currentPassword, "f");
1740
+ // Keyrings and encryption credentials are restored to their previous state
1741
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, currentEncryptionKey, "f");
1754
1742
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, currentSerializedKeyrings);
1755
1743
  throw e;
1756
1744
  }