@metamask-previews/keyring-controller 22.0.2-preview-4193b35 → 22.0.2-preview-13f36eb8

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,6 +7,22 @@ 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
+
15
+ ### Changed
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))
18
+
19
+ ### Removed
20
+
21
+ - **BREAKING:** The `cacheEncryptionKey` parameter has been removed from the `KeyringController` constructor options ([#5963](https://github.com/MetaMask/core/pull/5963))
22
+ - 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.
23
+ - **BREAKING:** The `submitEncryptionKey` method does not accept an `encryptionSalt` argument anymore ([#5963](https://github.com/MetaMask/core/pull/5963))
24
+ - The encryption salt is now always taken from the vault.
25
+
10
26
  ## [22.0.2]
11
27
 
12
28
  ### Fixed
@@ -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");
@@ -270,23 +270,17 @@ class KeyringController extends base_controller_1.BaseController {
270
270
  _KeyringController_vaultOperationMutex.set(this, new async_mutex_1.Mutex());
271
271
  _KeyringController_keyringBuilders.set(this, void 0);
272
272
  _KeyringController_encryptor.set(this, void 0);
273
- _KeyringController_cacheEncryptionKey.set(this, void 0);
274
273
  _KeyringController_keyrings.set(this, void 0);
275
274
  _KeyringController_unsupportedKeyrings.set(this, void 0);
276
- _KeyringController_password.set(this, void 0);
275
+ _KeyringController_encryptionKey.set(this, void 0);
277
276
  _KeyringController_qrKeyringStateListener.set(this, void 0);
278
277
  __classPrivateFieldSet(this, _KeyringController_keyringBuilders, keyringBuilders
279
278
  ? keyringBuilders.concat(defaultKeyringBuilders)
280
279
  : defaultKeyringBuilders, "f");
280
+ assertIsExportableKeyEncryptor(encryptor);
281
281
  __classPrivateFieldSet(this, _KeyringController_encryptor, encryptor, "f");
282
282
  __classPrivateFieldSet(this, _KeyringController_keyrings, [], "f");
283
283
  __classPrivateFieldSet(this, _KeyringController_unsupportedKeyrings, [], "f");
284
- // This option allows the controller to cache an exported key
285
- // for use in decrypting and encrypting data without password
286
- __classPrivateFieldSet(this, _KeyringController_cacheEncryptionKey, Boolean(options.cacheEncryptionKey), "f");
287
- if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
288
- assertIsExportableKeyEncryptor(encryptor);
289
- }
290
284
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_registerMessageHandlers).call(this);
291
285
  }
292
286
  /**
@@ -661,7 +655,7 @@ class KeyringController extends base_controller_1.BaseController {
661
655
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
662
656
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
663
657
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unsubscribeFromQRKeyringsEvents).call(this);
664
- __classPrivateFieldSet(this, _KeyringController_password, undefined, "f");
658
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, undefined, "f");
665
659
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
666
660
  this.update((state) => {
667
661
  state.isUnlocked = false;
@@ -845,16 +839,7 @@ class KeyringController extends base_controller_1.BaseController {
845
839
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
846
840
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
847
841
  assertIsValidPassword(password);
848
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
849
- // We need to clear encryption key and salt from state
850
- // to force the controller to re-encrypt the vault using
851
- // the new password.
852
- if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
853
- this.update((state) => {
854
- delete state.encryptionKey;
855
- delete state.encryptionSalt;
856
- });
857
- }
842
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveEncryptionKey).call(this, password);
858
843
  });
859
844
  }
860
845
  /**
@@ -862,12 +847,13 @@ class KeyringController extends base_controller_1.BaseController {
862
847
  * using the given encryption key and salt.
863
848
  *
864
849
  * @param encryptionKey - Key to unlock the keychain.
865
- * @param encryptionSalt - Salt to unlock the keychain.
866
850
  * @returns Promise resolving when the operation completes.
867
851
  */
868
- async submitEncryptionKey(encryptionKey, encryptionSalt) {
852
+ async submitEncryptionKey(encryptionKey) {
869
853
  const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
870
- const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, undefined, encryptionKey, encryptionSalt);
854
+ const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, {
855
+ exportedEncryptionKey: encryptionKey,
856
+ });
871
857
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
872
858
  return result;
873
859
  });
@@ -895,7 +881,7 @@ class KeyringController extends base_controller_1.BaseController {
895
881
  */
896
882
  async submitPassword(password) {
897
883
  const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
898
- const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, password);
884
+ const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, { password });
899
885
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
900
886
  return result;
901
887
  });
@@ -905,6 +891,12 @@ class KeyringController extends base_controller_1.BaseController {
905
891
  // can attempt to upgrade the vault.
906
892
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
907
893
  if (newMetadata || __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isNewEncryptionAvailable).call(this)) {
894
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveEncryptionKey).call(this, password, {
895
+ // If the vault is being upgraded, we want to ignore the metadata
896
+ // that is already in the vault, so we can effectively
897
+ // re-encrypt the vault with the new encryption config.
898
+ ignoreVaultKeyMetadata: true,
899
+ });
908
900
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
909
901
  }
910
902
  });
@@ -1159,7 +1151,7 @@ class KeyringController extends base_controller_1.BaseController {
1159
1151
  }
1160
1152
  }
1161
1153
  exports.KeyringController = KeyringController;
1162
- _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() {
1154
+ _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() {
1163
1155
  this.messagingSystem.registerActionHandler(`${name}:signMessage`, this.signMessage.bind(this));
1164
1156
  this.messagingSystem.registerActionHandler(`${name}:signEip7702Authorization`, this.signEip7702Authorization.bind(this));
1165
1157
  this.messagingSystem.registerActionHandler(`${name}:signPersonalMessage`, this.signPersonalMessage.bind(this));
@@ -1239,10 +1231,56 @@ async function _KeyringController_createNewVaultWithKeyring(password, keyring) {
1239
1231
  delete state.encryptionKey;
1240
1232
  delete state.encryptionSalt;
1241
1233
  });
1242
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1234
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveEncryptionKey).call(this, password);
1243
1235
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
1244
1236
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyringWithFirstAccount).call(this, keyring.type, keyring.opts);
1245
1237
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
1238
+ }, _KeyringController_deriveEncryptionKey =
1239
+ /**
1240
+ * Derive the vault encryption key from the provided password, and
1241
+ * assign it to the class variable for later use with cryptographic
1242
+ * functions.
1243
+ *
1244
+ * When the controller has a vault in its state, the key is derived
1245
+ * using the salt from the vault. If the vault is empty, a new salt
1246
+ * is generated and used to derive the key.
1247
+ *
1248
+ * @param password - The password to use for decryption or derivation.
1249
+ * @param options - Options for the key derivation.
1250
+ * @param options.ignoreVaultKeyMetadata - Whether to ignore the vault key metadata
1251
+ */
1252
+ async function _KeyringController_deriveEncryptionKey(password, options = {
1253
+ ignoreVaultKeyMetadata: false,
1254
+ }) {
1255
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1256
+ const { vault } = this.state;
1257
+ if (typeof password !== 'string') {
1258
+ throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
1259
+ }
1260
+ let salt, keyMetadata;
1261
+ if (vault && !options.ignoreVaultKeyMetadata) {
1262
+ const parsedVault = JSON.parse(vault);
1263
+ salt = parsedVault.salt;
1264
+ keyMetadata = parsedVault.keyMetadata;
1265
+ }
1266
+ else {
1267
+ salt = __classPrivateFieldGet(this, _KeyringController_encryptor, "f").generateSalt();
1268
+ }
1269
+ const exportedEncryptionKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").exportKey(await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").keyFromPassword(password, salt, true, keyMetadata));
1270
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, {
1271
+ salt,
1272
+ exported: exportedEncryptionKey,
1273
+ }, "f");
1274
+ }, _KeyringController_useEncryptionKey = function _KeyringController_useEncryptionKey(encryptionKey, encryptionSalt) {
1275
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1276
+ if (typeof encryptionKey !== 'string' ||
1277
+ typeof encryptionSalt !== 'string') {
1278
+ throw new TypeError(constants_1.KeyringControllerError.WrongEncryptionKeyType);
1279
+ }
1280
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, {
1281
+ salt: encryptionSalt,
1282
+ exported: encryptionKey,
1283
+ }, "f");
1246
1284
  }, _KeyringController_verifySeedPhrase =
1247
1285
  /**
1248
1286
  * Internal non-exclusive method to verify the seed phrase.
@@ -1331,7 +1369,7 @@ async function _KeyringController_getSerializedKeyrings({ includeUnsupported } =
1331
1369
  async function _KeyringController_getSessionState() {
1332
1370
  return {
1333
1371
  keyrings: await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this),
1334
- password: __classPrivateFieldGet(this, _KeyringController_password, "f"),
1372
+ encryptionKey: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f"),
1335
1373
  };
1336
1374
  }, _KeyringController_restoreSerializedKeyrings =
1337
1375
  /**
@@ -1360,54 +1398,28 @@ async function _KeyringController_restoreSerializedKeyrings(serializedKeyrings)
1360
1398
  * Unlock Keyrings, decrypting the vault and deserializing all
1361
1399
  * keyrings contained in it, using a password or an encryption key with salt.
1362
1400
  *
1363
- * @param password - The keyring controller password.
1364
- * @param encryptionKey - An exported key string to unlock keyrings with.
1365
- * @param encryptionSalt - The salt used to encrypt the vault.
1401
+ * @param credentials - The credentials to unlock the keyrings.
1366
1402
  * @returns A promise resolving to the deserialized keyrings array.
1367
1403
  */
1368
- async function _KeyringController_unlockKeyrings(password, encryptionKey, encryptionSalt) {
1404
+ async function _KeyringController_unlockKeyrings(credentials) {
1369
1405
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
1370
- const encryptedVault = this.state.vault;
1371
- if (!encryptedVault) {
1406
+ if (!this.state.vault) {
1372
1407
  throw new Error(constants_1.KeyringControllerError.VaultError);
1373
1408
  }
1374
- let vault;
1375
- const updatedState = {};
1376
- if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
1377
- assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
1378
- if (password) {
1379
- const result = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithDetail(password, encryptedVault);
1380
- vault = result.vault;
1381
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1382
- updatedState.encryptionKey = result.exportedKeyString;
1383
- updatedState.encryptionSalt = result.salt;
1384
- }
1385
- else {
1386
- const parsedEncryptedVault = JSON.parse(encryptedVault);
1387
- if (encryptionSalt !== parsedEncryptedVault.salt) {
1388
- throw new Error(constants_1.KeyringControllerError.ExpiredCredentials);
1389
- }
1390
- if (typeof encryptionKey !== 'string') {
1391
- throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
1392
- }
1393
- const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
1394
- vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(key, parsedEncryptedVault);
1395
- // This call is required on the first call because encryptionKey
1396
- // is not yet inside the memStore
1397
- updatedState.encryptionKey = encryptionKey;
1398
- // we can safely assume that encryptionSalt is defined here
1399
- // because we compare it with the salt from the vault
1400
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1401
- updatedState.encryptionSalt = encryptionSalt;
1402
- }
1409
+ const parsedEncryptedVault = JSON.parse(this.state.vault);
1410
+ if ('password' in credentials) {
1411
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveEncryptionKey).call(this, credentials.password);
1403
1412
  }
1404
1413
  else {
1405
- if (typeof password !== 'string') {
1406
- throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
1407
- }
1408
- vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, encryptedVault);
1409
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1414
+ const { exportedEncryptionKey } = credentials;
1415
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_useEncryptionKey).call(this, exportedEncryptionKey, parsedEncryptedVault.salt);
1410
1416
  }
1417
+ const encryptionKey = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")?.exported;
1418
+ if (!encryptionKey) {
1419
+ throw new Error(constants_1.KeyringControllerError.MissingCredentials);
1420
+ }
1421
+ const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
1422
+ const vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(key, parsedEncryptedVault);
1411
1423
  if (!isSerializedKeyringsArray(vault)) {
1412
1424
  throw new Error(constants_1.KeyringControllerError.VaultDataError);
1413
1425
  }
@@ -1415,10 +1427,8 @@ async function _KeyringController_unlockKeyrings(password, encryptionKey, encryp
1415
1427
  const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
1416
1428
  this.update((state) => {
1417
1429
  state.keyrings = updatedKeyrings;
1418
- if (updatedState.encryptionKey || updatedState.encryptionSalt) {
1419
- state.encryptionKey = updatedState.encryptionKey;
1420
- state.encryptionSalt = updatedState.encryptionSalt;
1421
- }
1430
+ state.encryptionKey = encryptionKey;
1431
+ state.encryptionSalt = parsedEncryptedVault.salt;
1422
1432
  });
1423
1433
  return { keyrings, newMetadata };
1424
1434
  });
@@ -1426,57 +1436,38 @@ async function _KeyringController_unlockKeyrings(password, encryptionKey, encryp
1426
1436
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
1427
1437
  // Ensure no duplicate accounts are persisted.
1428
1438
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoDuplicateAccounts).call(this);
1429
- const { encryptionKey, encryptionSalt, vault } = this.state;
1430
- // READ THIS CAREFULLY:
1431
- // We do check if the vault is still considered up-to-date, if not, we would not re-use the
1432
- // cached key and we will re-generate a new one (based on the password).
1433
- //
1434
- // This helps doing seamless updates of the vault. Useful in case we change some cryptographic
1435
- // parameters to the KDF.
1436
- const useCachedKey = encryptionKey && vault && __classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated?.(vault);
1437
- if (!__classPrivateFieldGet(this, _KeyringController_password, "f") && !encryptionKey) {
1439
+ if (!__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")) {
1438
1440
  throw new Error(constants_1.KeyringControllerError.MissingCredentials);
1439
1441
  }
1440
1442
  const serializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
1441
1443
  if (!serializedKeyrings.some((keyring) => keyring.type === KeyringTypes.hd)) {
1442
1444
  throw new Error(constants_1.KeyringControllerError.NoHdKeyring);
1443
1445
  }
1444
- const updatedState = {};
1445
- if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
1446
- assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
1447
- if (useCachedKey) {
1448
- const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
1449
- const vaultJSON = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithKey(key, serializedKeyrings);
1450
- vaultJSON.salt = encryptionSalt;
1451
- updatedState.vault = JSON.stringify(vaultJSON);
1452
- }
1453
- else if (__classPrivateFieldGet(this, _KeyringController_password, "f")) {
1454
- const { vault: newVault, exportedKeyString } = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithDetail(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
1455
- updatedState.vault = newVault;
1456
- updatedState.encryptionKey = exportedKeyString;
1457
- }
1458
- }
1459
- else {
1460
- assertIsValidPassword(__classPrivateFieldGet(this, _KeyringController_password, "f"));
1461
- updatedState.vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encrypt(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
1462
- }
1463
- if (!updatedState.vault) {
1464
- throw new Error(constants_1.KeyringControllerError.MissingVaultData);
1446
+ const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").exported);
1447
+ const encryptedVault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithKey(key, serializedKeyrings);
1448
+ if (__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").salt) {
1449
+ // We need to include the salt used to derive
1450
+ // the encryption key, to be able to derive it
1451
+ // from password again.
1452
+ encryptedVault.salt = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").salt;
1465
1453
  }
1454
+ const updatedState = {
1455
+ vault: JSON.stringify(encryptedVault),
1456
+ encryptionKey: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").exported,
1457
+ encryptionSalt: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").salt,
1458
+ };
1466
1459
  const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
1467
1460
  this.update((state) => {
1468
1461
  state.vault = updatedState.vault;
1469
1462
  state.keyrings = updatedKeyrings;
1470
- if (updatedState.encryptionKey) {
1471
- state.encryptionKey = updatedState.encryptionKey;
1472
- state.encryptionSalt = JSON.parse(updatedState.vault).salt;
1473
- }
1463
+ state.encryptionKey = updatedState.encryptionKey;
1464
+ state.encryptionSalt = updatedState.encryptionSalt;
1474
1465
  });
1475
1466
  return true;
1476
1467
  });
1477
1468
  }, _KeyringController_isNewEncryptionAvailable = function _KeyringController_isNewEncryptionAvailable() {
1478
1469
  const { vault } = this.state;
1479
- if (!vault || !__classPrivateFieldGet(this, _KeyringController_password, "f") || !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated) {
1470
+ if (!vault || !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated) {
1480
1471
  return false;
1481
1472
  }
1482
1473
  return !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated(vault);
@@ -1715,13 +1706,16 @@ async function _KeyringController_persistOrRollback(callback) {
1715
1706
  async function _KeyringController_withRollback(callback) {
1716
1707
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async ({ releaseLock }) => {
1717
1708
  const currentSerializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
1718
- const currentPassword = __classPrivateFieldGet(this, _KeyringController_password, "f");
1709
+ const currentEncryptionKey = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")?.exported;
1710
+ const currentEncryptionSalt = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")?.salt;
1719
1711
  try {
1720
1712
  return await callback({ releaseLock });
1721
1713
  }
1722
1714
  catch (e) {
1723
- // Keyrings and password are restored to their previous state
1724
- __classPrivateFieldSet(this, _KeyringController_password, currentPassword, "f");
1715
+ // Keyrings and encryption credentials are restored to their previous state
1716
+ if (currentEncryptionKey && currentEncryptionSalt) {
1717
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_useEncryptionKey).call(this, currentEncryptionKey, currentEncryptionSalt);
1718
+ }
1725
1719
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, currentSerializedKeyrings);
1726
1720
  throw e;
1727
1721
  }