@metamask-previews/keyring-controller 24.0.0-preview-8d5916c4 → 24.0.0-preview-704ae19a

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
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
17
17
  - **BREAKING:** The `KeyringController` constructor options now require an encryptor ([#7127](https://github.com/MetaMask/core/pull/7127))
18
18
  - The `encryptor` constructor option was previously optional and defaulted to an instance of `@metamask/browser-passworder`.
19
19
  - **BREAKING:** The `GenericEncryptor` and `ExportableKeyEncryptor` types have been merged into a single `Encryptor` type ([#7127](https://github.com/MetaMask/core/pull/7127))
20
+ - **BREAKING:** The `Encryptor` type requires `exportKey`, `keyFromPassword` and `generateSalt` methods ([#7128](https://github.com/MetaMask/core/pull/7128))
20
21
 
21
22
  ### Removed
22
23
 
@@ -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_keyrings, _KeyringController_unsupportedKeyrings, _KeyringController_password, _KeyringController_registerMessageHandlers, _KeyringController_getKeyringById, _KeyringController_getKeyringByIdOrDefault, _KeyringController_getKeyringMetadata, _KeyringController_getKeyringBuilderForType, _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_registerMessageHandlers, _KeyringController_getKeyringById, _KeyringController_getKeyringByIdOrDefault, _KeyringController_getKeyringMetadata, _KeyringController_getKeyringBuilderForType, _KeyringController_createNewVaultWithKeyring, _KeyringController_deriveAndSetEncryptionKey, _KeyringController_setEncryptionKey, _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");
@@ -289,7 +289,7 @@ class KeyringController extends base_controller_1.BaseController {
289
289
  _KeyringController_encryptor.set(this, void 0);
290
290
  _KeyringController_keyrings.set(this, void 0);
291
291
  _KeyringController_unsupportedKeyrings.set(this, void 0);
292
- _KeyringController_password.set(this, void 0);
292
+ _KeyringController_encryptionKey.set(this, void 0);
293
293
  __classPrivateFieldSet(this, _KeyringController_keyringBuilders, keyringBuilders
294
294
  ? keyringBuilders.concat(defaultKeyringBuilders)
295
295
  : defaultKeyringBuilders, "f");
@@ -666,7 +666,7 @@ class KeyringController extends base_controller_1.BaseController {
666
666
  async setLocked() {
667
667
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
668
668
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
669
- __classPrivateFieldSet(this, _KeyringController_password, undefined, "f");
669
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, undefined, "f");
670
670
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
671
671
  this.update((state) => {
672
672
  state.isUnlocked = false;
@@ -848,19 +848,10 @@ class KeyringController extends base_controller_1.BaseController {
848
848
  */
849
849
  changePassword(password) {
850
850
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
851
- // If the password is the same, do nothing.
852
- if (__classPrivateFieldGet(this, _KeyringController_password, "f") === password) {
853
- return Promise.resolve();
854
- }
855
851
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
856
852
  assertIsValidPassword(password);
857
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
858
- // We need to clear encryption key and salt from state
859
- // to force the controller to re-encrypt the vault using
860
- // the new password.
861
- this.update((state) => {
862
- delete state.encryptionKey;
863
- delete state.encryptionSalt;
853
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveAndSetEncryptionKey).call(this, password, {
854
+ ignoreExistingVault: true,
864
855
  });
865
856
  });
866
857
  }
@@ -875,7 +866,10 @@ class KeyringController extends base_controller_1.BaseController {
875
866
  */
876
867
  async submitEncryptionKey(encryptionKey, encryptionSalt) {
877
868
  const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
878
- const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, undefined, encryptionKey, encryptionSalt);
869
+ const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, {
870
+ encryptionKey,
871
+ encryptionSalt,
872
+ });
879
873
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
880
874
  return result;
881
875
  });
@@ -902,9 +896,8 @@ class KeyringController extends base_controller_1.BaseController {
902
896
  async exportEncryptionKey() {
903
897
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
904
898
  return await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async () => {
905
- const { encryptionKey } = this.state;
906
- assertIsEncryptionKeySet(encryptionKey);
907
- return encryptionKey;
899
+ assertIsEncryptionKeySet(__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")?.serialized);
900
+ return __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").serialized;
908
901
  });
909
902
  }
910
903
  /**
@@ -916,7 +909,7 @@ class KeyringController extends base_controller_1.BaseController {
916
909
  */
917
910
  async submitPassword(password) {
918
911
  const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
919
- const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, password);
912
+ const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, { password });
920
913
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
921
914
  return result;
922
915
  });
@@ -926,6 +919,12 @@ class KeyringController extends base_controller_1.BaseController {
926
919
  // can attempt to upgrade the vault.
927
920
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
928
921
  if (newMetadata || __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isNewEncryptionAvailable).call(this)) {
922
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveAndSetEncryptionKey).call(this, password, {
923
+ // If the vault is being upgraded, we want to ignore the metadata
924
+ // that is already in the vault, so we can effectively
925
+ // re-encrypt the vault with the new encryption config.
926
+ ignoreExistingVault: true,
927
+ });
929
928
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
930
929
  }
931
930
  });
@@ -988,7 +987,7 @@ class KeyringController extends base_controller_1.BaseController {
988
987
  }
989
988
  }
990
989
  exports.KeyringController = KeyringController;
991
- _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_password = new WeakMap(), _KeyringController_instances = new WeakSet(), _KeyringController_registerMessageHandlers = function _KeyringController_registerMessageHandlers() {
990
+ _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_instances = new WeakSet(), _KeyringController_registerMessageHandlers = function _KeyringController_registerMessageHandlers() {
992
991
  this.messenger.registerActionHandler(`${name}:signMessage`, this.signMessage.bind(this));
993
992
  this.messenger.registerActionHandler(`${name}:signEip7702Authorization`, this.signEip7702Authorization.bind(this));
994
993
  this.messenger.registerActionHandler(`${name}:signPersonalMessage`, this.signPersonalMessage.bind(this));
@@ -1047,10 +1046,70 @@ async function _KeyringController_createNewVaultWithKeyring(password, keyring) {
1047
1046
  delete state.encryptionKey;
1048
1047
  delete state.encryptionSalt;
1049
1048
  });
1050
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1049
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveAndSetEncryptionKey).call(this, password, {
1050
+ ignoreExistingVault: true,
1051
+ });
1051
1052
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
1052
1053
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyringWithFirstAccount).call(this, keyring.type, keyring.opts);
1053
1054
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
1055
+ }, _KeyringController_deriveAndSetEncryptionKey =
1056
+ /**
1057
+ * Derive the vault encryption key from the provided password, and
1058
+ * assign it to the instance variable for later use with cryptographic
1059
+ * functions.
1060
+ *
1061
+ * When the controller has a vault in its state, the key is derived
1062
+ * using the salt from the vault. If the vault is empty, a new salt
1063
+ * is generated and used to derive the key.
1064
+ *
1065
+ * If `options.ignoreExistingVault` is set to `true`, the existing
1066
+ * vault is completely ignored: the new key won't be able to decrypt
1067
+ * the existing vault, and should be used to re-encrypt it.
1068
+ *
1069
+ * @param password - The password to use for decryption or derivation.
1070
+ * @param options - Options for the key derivation.
1071
+ * @param options.ignoreExistingVault - Whether to ignore the existing vault salt and key metadata
1072
+ */
1073
+ async function _KeyringController_deriveAndSetEncryptionKey(password, options = {
1074
+ ignoreExistingVault: false,
1075
+ }) {
1076
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1077
+ const { vault } = this.state;
1078
+ if (typeof password !== 'string') {
1079
+ throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
1080
+ }
1081
+ let serializedEncryptionKey, salt;
1082
+ if (vault && !options.ignoreExistingVault) {
1083
+ // The `decryptWithDetail` method is being used here instead of
1084
+ // `keyFromPassword` + `exportKey` to let the encryptor handle
1085
+ // any legacy encryption formats and metadata that might be
1086
+ // present (or absent) in the vault.
1087
+ const { exportedKeyString, salt: existingSalt } = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithDetail(password, vault);
1088
+ serializedEncryptionKey = exportedKeyString;
1089
+ salt = existingSalt;
1090
+ }
1091
+ else {
1092
+ salt = __classPrivateFieldGet(this, _KeyringController_encryptor, "f").generateSalt();
1093
+ serializedEncryptionKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").exportKey(await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").keyFromPassword(password, salt, true));
1094
+ }
1095
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, {
1096
+ salt,
1097
+ serialized: serializedEncryptionKey,
1098
+ }, "f");
1099
+ }, _KeyringController_setEncryptionKey = function _KeyringController_setEncryptionKey(encryptionKey, keyDerivationSalt) {
1100
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1101
+ if (typeof encryptionKey !== 'string' ||
1102
+ typeof keyDerivationSalt !== 'string') {
1103
+ throw new TypeError(constants_1.KeyringControllerError.WrongEncryptionKeyType);
1104
+ }
1105
+ const { vault } = this.state;
1106
+ if (vault && JSON.parse(vault).salt !== keyDerivationSalt) {
1107
+ throw new Error(constants_1.KeyringControllerError.ExpiredCredentials);
1108
+ }
1109
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, {
1110
+ salt: keyDerivationSalt,
1111
+ serialized: encryptionKey,
1112
+ }, "f");
1054
1113
  }, _KeyringController_verifySeedPhrase =
1055
1114
  /**
1056
1115
  * Internal non-exclusive method to verify the seed phrase.
@@ -1064,7 +1123,6 @@ async function _KeyringController_verifySeedPhrase(keyringId) {
1064
1123
  if (!keyring) {
1065
1124
  throw new Error(constants_1.KeyringControllerError.KeyringNotFound);
1066
1125
  }
1067
- // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
1068
1126
  if (keyring.type !== KeyringTypes.hd) {
1069
1127
  throw new Error(constants_1.KeyringControllerError.UnsupportedVerifySeedPhrase);
1070
1128
  }
@@ -1131,7 +1189,7 @@ async function _KeyringController_getSerializedKeyrings({ includeUnsupported } =
1131
1189
  return serializedKeyrings;
1132
1190
  }, _KeyringController_getSessionState =
1133
1191
  /**
1134
- * Get a snapshot of session data held by class variables.
1192
+ * Get a snapshot of session data held by instance variables.
1135
1193
  *
1136
1194
  * @returns An object with serialized keyrings, keyrings metadata,
1137
1195
  * and the user password.
@@ -1139,7 +1197,7 @@ async function _KeyringController_getSerializedKeyrings({ includeUnsupported } =
1139
1197
  async function _KeyringController_getSessionState() {
1140
1198
  return {
1141
1199
  keyrings: await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this),
1142
- password: __classPrivateFieldGet(this, _KeyringController_password, "f"),
1200
+ encryptionKey: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f"),
1143
1201
  };
1144
1202
  }, _KeyringController_restoreSerializedKeyrings =
1145
1203
  /**
@@ -1168,44 +1226,27 @@ async function _KeyringController_restoreSerializedKeyrings(serializedKeyrings)
1168
1226
  * Unlock Keyrings, decrypting the vault and deserializing all
1169
1227
  * keyrings contained in it, using a password or an encryption key with salt.
1170
1228
  *
1171
- * @param password - The keyring controller password.
1172
- * @param encryptionKey - An exported key string to unlock keyrings with.
1173
- * @param encryptionSalt - The salt used to encrypt the vault.
1229
+ * @param credentials - The credentials to unlock the keyrings.
1174
1230
  * @returns A promise resolving to the deserialized keyrings array.
1175
1231
  */
1176
- async function _KeyringController_unlockKeyrings(password, encryptionKey, encryptionSalt) {
1232
+ async function _KeyringController_unlockKeyrings(credentials) {
1177
1233
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
1178
- const encryptedVault = this.state.vault;
1179
- if (!encryptedVault) {
1234
+ if (!this.state.vault) {
1180
1235
  throw new Error(constants_1.KeyringControllerError.VaultError);
1181
1236
  }
1182
- let vault;
1183
- const updatedState = {};
1184
- if (password) {
1185
- const result = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithDetail(password, encryptedVault);
1186
- vault = result.vault;
1187
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1188
- updatedState.encryptionKey = result.exportedKeyString;
1189
- updatedState.encryptionSalt = result.salt;
1237
+ const parsedEncryptedVault = JSON.parse(this.state.vault);
1238
+ if ('password' in credentials) {
1239
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveAndSetEncryptionKey).call(this, credentials.password);
1190
1240
  }
1191
1241
  else {
1192
- const parsedEncryptedVault = JSON.parse(encryptedVault);
1193
- if (encryptionSalt && encryptionSalt !== parsedEncryptedVault.salt) {
1194
- throw new Error(constants_1.KeyringControllerError.ExpiredCredentials);
1195
- }
1196
- else {
1197
- encryptionSalt = parsedEncryptedVault.salt;
1198
- }
1199
- if (typeof encryptionKey !== 'string') {
1200
- throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
1201
- }
1202
- const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
1203
- vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(key, parsedEncryptedVault);
1204
- // This call is required on the first call because encryptionKey
1205
- // is not yet inside the memStore
1206
- updatedState.encryptionKey = encryptionKey;
1207
- updatedState.encryptionSalt = encryptionSalt;
1242
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setEncryptionKey).call(this, credentials.encryptionKey, credentials.encryptionSalt || parsedEncryptedVault.salt);
1208
1243
  }
1244
+ const encryptionKey = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")?.serialized;
1245
+ if (!encryptionKey) {
1246
+ throw new Error(constants_1.KeyringControllerError.MissingCredentials);
1247
+ }
1248
+ const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
1249
+ const vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(key, parsedEncryptedVault);
1209
1250
  if (!isSerializedKeyringsArray(vault)) {
1210
1251
  throw new Error(constants_1.KeyringControllerError.VaultDataError);
1211
1252
  }
@@ -1213,10 +1254,8 @@ async function _KeyringController_unlockKeyrings(password, encryptionKey, encryp
1213
1254
  const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
1214
1255
  this.update((state) => {
1215
1256
  state.keyrings = updatedKeyrings;
1216
- if (updatedState.encryptionKey || updatedState.encryptionSalt) {
1217
- state.encryptionKey = updatedState.encryptionKey;
1218
- state.encryptionSalt = updatedState.encryptionSalt;
1219
- }
1257
+ state.encryptionKey = encryptionKey;
1258
+ state.encryptionSalt = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")?.salt;
1220
1259
  });
1221
1260
  return { keyrings, newMetadata };
1222
1261
  });
@@ -1224,50 +1263,36 @@ async function _KeyringController_unlockKeyrings(password, encryptionKey, encryp
1224
1263
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
1225
1264
  // Ensure no duplicate accounts are persisted.
1226
1265
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoDuplicateAccounts).call(this);
1227
- const { encryptionKey, encryptionSalt, vault } = this.state;
1228
- // READ THIS CAREFULLY:
1229
- // We do check if the vault is still considered up-to-date, if not, we would not re-use the
1230
- // cached key and we will re-generate a new one (based on the password).
1231
- //
1232
- // This helps doing seamless updates of the vault. Useful in case we change some cryptographic
1233
- // parameters to the KDF.
1234
- const useCachedKey = encryptionKey && vault && __classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated?.(vault);
1235
- if (!__classPrivateFieldGet(this, _KeyringController_password, "f") && !encryptionKey) {
1266
+ if (!__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")) {
1236
1267
  throw new Error(constants_1.KeyringControllerError.MissingCredentials);
1237
1268
  }
1238
1269
  const serializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
1239
1270
  if (!serializedKeyrings.some((keyring) => keyring.type === KeyringTypes.hd)) {
1240
1271
  throw new Error(constants_1.KeyringControllerError.NoHdKeyring);
1241
1272
  }
1242
- const updatedState = {};
1243
- if (useCachedKey) {
1244
- const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
1245
- const vaultJSON = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithKey(key, serializedKeyrings);
1246
- vaultJSON.salt = encryptionSalt;
1247
- updatedState.vault = JSON.stringify(vaultJSON);
1248
- }
1249
- else if (__classPrivateFieldGet(this, _KeyringController_password, "f")) {
1250
- const { vault: newVault, exportedKeyString } = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithDetail(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
1251
- updatedState.vault = newVault;
1252
- updatedState.encryptionKey = exportedKeyString;
1253
- }
1254
- if (!updatedState.vault) {
1255
- throw new Error(constants_1.KeyringControllerError.MissingVaultData);
1256
- }
1273
+ const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").serialized);
1274
+ const encryptedVault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithKey(key, serializedKeyrings);
1275
+ // We need to include the salt used to derive
1276
+ // the encryption key, to be able to derive it
1277
+ // from password again.
1278
+ encryptedVault.salt = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").salt;
1279
+ const updatedState = {
1280
+ vault: JSON.stringify(encryptedVault),
1281
+ encryptionKey: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").serialized,
1282
+ encryptionSalt: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").salt,
1283
+ };
1257
1284
  const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
1258
1285
  this.update((state) => {
1259
1286
  state.vault = updatedState.vault;
1260
1287
  state.keyrings = updatedKeyrings;
1261
- if (updatedState.encryptionKey) {
1262
- state.encryptionKey = updatedState.encryptionKey;
1263
- state.encryptionSalt = JSON.parse(updatedState.vault).salt;
1264
- }
1288
+ state.encryptionKey = updatedState.encryptionKey;
1289
+ state.encryptionSalt = updatedState.encryptionSalt;
1265
1290
  });
1266
1291
  return true;
1267
1292
  });
1268
1293
  }, _KeyringController_isNewEncryptionAvailable = function _KeyringController_isNewEncryptionAvailable() {
1269
1294
  const { vault } = this.state;
1270
- if (!vault || !__classPrivateFieldGet(this, _KeyringController_password, "f") || !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated) {
1295
+ if (!vault || !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated) {
1271
1296
  return false;
1272
1297
  }
1273
1298
  return !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated(vault);
@@ -1501,13 +1526,13 @@ async function _KeyringController_persistOrRollback(callback) {
1501
1526
  async function _KeyringController_withRollback(callback) {
1502
1527
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async ({ releaseLock }) => {
1503
1528
  const currentSerializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
1504
- const currentPassword = __classPrivateFieldGet(this, _KeyringController_password, "f");
1529
+ const currentEncryptionKey = (0, lodash_1.cloneDeep)(__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f"));
1505
1530
  try {
1506
1531
  return await callback({ releaseLock });
1507
1532
  }
1508
1533
  catch (e) {
1509
- // Keyrings and password are restored to their previous state
1510
- __classPrivateFieldSet(this, _KeyringController_password, currentPassword, "f");
1534
+ // Keyrings and encryption credentials are restored to their previous state
1535
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, currentEncryptionKey, "f");
1511
1536
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, currentSerializedKeyrings);
1512
1537
  throw e;
1513
1538
  }