@metamask-previews/keyring-controller 24.0.0-preview-cb2e5c04 → 24.0.0-preview-82b6f2e
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 +0 -21
- package/dist/KeyringController.cjs +135 -117
- package/dist/KeyringController.cjs.map +1 -1
- package/dist/KeyringController.d.cts +29 -49
- package/dist/KeyringController.d.cts.map +1 -1
- package/dist/KeyringController.d.mts +29 -49
- package/dist/KeyringController.d.mts.map +1 -1
- package/dist/KeyringController.mjs +136 -118
- package/dist/KeyringController.mjs.map +1 -1
- package/dist/constants.cjs +0 -1
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +0 -1
- package/dist/constants.d.cts.map +1 -1
- package/dist/constants.d.mts +0 -1
- package/dist/constants.d.mts.map +1 -1
- package/dist/constants.mjs +0 -1
- package/dist/constants.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,27 +7,6 @@ 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 `EncryptionKey`, `SupportedKeyDerivationOptions` and `EncryptionResult` type parameters to the `KeyringController`, `ExportableKeyEncryptor` and `KeyringControllerOptions` types ([#7127](https://github.com/MetaMask/core/pull/7127))
|
|
13
|
-
- This type parameter allows specifying the encryption key, key derivation options and encryption result types supported by the injected encryptor, defaulting to `@metamask/browser-passworder` types.
|
|
14
|
-
|
|
15
|
-
### Changed
|
|
16
|
-
|
|
17
|
-
- **BREAKING:** The `KeyringController` constructor options now require an encryptor ([#7127](https://github.com/MetaMask/core/pull/7127))
|
|
18
|
-
- The `encryptor` constructor option was previously optional and defaulted to an instance of `@metamask/browser-passworder`.
|
|
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 ([#7127](https://github.com/MetaMask/core/pull/7127))
|
|
21
|
-
|
|
22
|
-
### Removed
|
|
23
|
-
|
|
24
|
-
- **BREAKING:** The `cacheEncryptionKey` parameter has been removed from the `KeyringController` constructor options ([#7127](https://github.com/MetaMask/core/pull/7127))
|
|
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
|
-
|
|
27
|
-
### Fixed
|
|
28
|
-
|
|
29
|
-
- Fixed incorrect type for `decryptWithKey` method of `ExportableKeyEncryptor` ([#7127](https://github.com/MetaMask/core/pull/7127))
|
|
30
|
-
|
|
31
10
|
## [24.0.0]
|
|
32
11
|
|
|
33
12
|
### Changed
|
|
@@ -36,11 +36,12 @@ 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,
|
|
39
|
+
var _KeyringController_instances, _KeyringController_controllerOperationMutex, _KeyringController_vaultOperationMutex, _KeyringController_keyringBuilders, _KeyringController_encryptor, _KeyringController_cacheEncryptionKey, _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;
|
|
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");
|
|
43
43
|
const base_controller_1 = require("@metamask/base-controller");
|
|
44
|
+
const encryptorUtils = __importStar(require("@metamask/browser-passworder"));
|
|
44
45
|
const eth_hd_keyring_1 = require("@metamask/eth-hd-keyring");
|
|
45
46
|
const eth_sig_util_1 = require("@metamask/eth-sig-util");
|
|
46
47
|
const eth_simple_keyring_1 = __importDefault(require("@metamask/eth-simple-keyring"));
|
|
@@ -135,6 +136,23 @@ function assertHasUint8ArrayMnemonic(keyring) {
|
|
|
135
136
|
throw new Error("Can't get mnemonic bytes from keyring");
|
|
136
137
|
}
|
|
137
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Assert that the provided encryptor supports
|
|
141
|
+
* encryption and encryption key export.
|
|
142
|
+
*
|
|
143
|
+
* @param encryptor - The encryptor to check.
|
|
144
|
+
* @throws If the encryptor does not support key encryption.
|
|
145
|
+
*/
|
|
146
|
+
function assertIsExportableKeyEncryptor(encryptor) {
|
|
147
|
+
if (!('importKey' in encryptor &&
|
|
148
|
+
typeof encryptor.importKey === 'function' &&
|
|
149
|
+
'decryptWithKey' in encryptor &&
|
|
150
|
+
typeof encryptor.decryptWithKey === 'function' &&
|
|
151
|
+
'encryptWithKey' in encryptor &&
|
|
152
|
+
typeof encryptor.encryptWithKey === 'function')) {
|
|
153
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedEncryptionKeyExport);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
138
156
|
/**
|
|
139
157
|
* Assert that the provided password is a valid non-empty string.
|
|
140
158
|
*
|
|
@@ -241,7 +259,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
241
259
|
* @param options.state - Initial state to set on this controller.
|
|
242
260
|
*/
|
|
243
261
|
constructor(options) {
|
|
244
|
-
const { encryptor, keyringBuilders, messenger, state } = options;
|
|
262
|
+
const { encryptor = encryptorUtils, keyringBuilders, messenger, state, } = options;
|
|
245
263
|
super({
|
|
246
264
|
name,
|
|
247
265
|
metadata: {
|
|
@@ -287,15 +305,22 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
287
305
|
_KeyringController_vaultOperationMutex.set(this, new async_mutex_1.Mutex());
|
|
288
306
|
_KeyringController_keyringBuilders.set(this, void 0);
|
|
289
307
|
_KeyringController_encryptor.set(this, void 0);
|
|
308
|
+
_KeyringController_cacheEncryptionKey.set(this, void 0);
|
|
290
309
|
_KeyringController_keyrings.set(this, void 0);
|
|
291
310
|
_KeyringController_unsupportedKeyrings.set(this, void 0);
|
|
292
|
-
|
|
311
|
+
_KeyringController_password.set(this, void 0);
|
|
293
312
|
__classPrivateFieldSet(this, _KeyringController_keyringBuilders, keyringBuilders
|
|
294
313
|
? keyringBuilders.concat(defaultKeyringBuilders)
|
|
295
314
|
: defaultKeyringBuilders, "f");
|
|
296
315
|
__classPrivateFieldSet(this, _KeyringController_encryptor, encryptor, "f");
|
|
297
316
|
__classPrivateFieldSet(this, _KeyringController_keyrings, [], "f");
|
|
298
317
|
__classPrivateFieldSet(this, _KeyringController_unsupportedKeyrings, [], "f");
|
|
318
|
+
// This option allows the controller to cache an exported key
|
|
319
|
+
// for use in decrypting and encrypting data without password
|
|
320
|
+
__classPrivateFieldSet(this, _KeyringController_cacheEncryptionKey, Boolean(options.cacheEncryptionKey), "f");
|
|
321
|
+
if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
|
|
322
|
+
assertIsExportableKeyEncryptor(encryptor);
|
|
323
|
+
}
|
|
299
324
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_registerMessageHandlers).call(this);
|
|
300
325
|
}
|
|
301
326
|
/**
|
|
@@ -666,7 +691,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
666
691
|
async setLocked() {
|
|
667
692
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
|
|
668
693
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
669
|
-
__classPrivateFieldSet(this,
|
|
694
|
+
__classPrivateFieldSet(this, _KeyringController_password, undefined, "f");
|
|
670
695
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
|
|
671
696
|
this.update((state) => {
|
|
672
697
|
state.isUnlocked = false;
|
|
@@ -848,11 +873,22 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
848
873
|
*/
|
|
849
874
|
changePassword(password) {
|
|
850
875
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
|
|
876
|
+
// If the password is the same, do nothing.
|
|
877
|
+
if (__classPrivateFieldGet(this, _KeyringController_password, "f") === password) {
|
|
878
|
+
return Promise.resolve();
|
|
879
|
+
}
|
|
851
880
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
|
|
852
881
|
assertIsValidPassword(password);
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
882
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
883
|
+
// We need to clear encryption key and salt from state
|
|
884
|
+
// to force the controller to re-encrypt the vault using
|
|
885
|
+
// the new password.
|
|
886
|
+
if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
|
|
887
|
+
this.update((state) => {
|
|
888
|
+
delete state.encryptionKey;
|
|
889
|
+
delete state.encryptionSalt;
|
|
890
|
+
});
|
|
891
|
+
}
|
|
856
892
|
});
|
|
857
893
|
}
|
|
858
894
|
/**
|
|
@@ -866,10 +902,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
866
902
|
*/
|
|
867
903
|
async submitEncryptionKey(encryptionKey, encryptionSalt) {
|
|
868
904
|
const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
869
|
-
const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this,
|
|
870
|
-
encryptionKey,
|
|
871
|
-
encryptionSalt,
|
|
872
|
-
});
|
|
905
|
+
const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, undefined, encryptionKey, encryptionSalt);
|
|
873
906
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
874
907
|
return result;
|
|
875
908
|
});
|
|
@@ -896,8 +929,9 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
896
929
|
async exportEncryptionKey() {
|
|
897
930
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
|
|
898
931
|
return await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async () => {
|
|
899
|
-
|
|
900
|
-
|
|
932
|
+
const { encryptionKey } = this.state;
|
|
933
|
+
assertIsEncryptionKeySet(encryptionKey);
|
|
934
|
+
return encryptionKey;
|
|
901
935
|
});
|
|
902
936
|
}
|
|
903
937
|
/**
|
|
@@ -909,7 +943,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
909
943
|
*/
|
|
910
944
|
async submitPassword(password) {
|
|
911
945
|
const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
912
|
-
const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this,
|
|
946
|
+
const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, password);
|
|
913
947
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
914
948
|
return result;
|
|
915
949
|
});
|
|
@@ -919,12 +953,6 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
919
953
|
// can attempt to upgrade the vault.
|
|
920
954
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
921
955
|
if (newMetadata || __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isNewEncryptionAvailable).call(this)) {
|
|
922
|
-
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveEncryptionKey).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
|
-
});
|
|
928
956
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
|
|
929
957
|
}
|
|
930
958
|
});
|
|
@@ -987,7 +1015,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
987
1015
|
}
|
|
988
1016
|
}
|
|
989
1017
|
exports.KeyringController = KeyringController;
|
|
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(),
|
|
1018
|
+
_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_instances = new WeakSet(), _KeyringController_registerMessageHandlers = function _KeyringController_registerMessageHandlers() {
|
|
991
1019
|
this.messenger.registerActionHandler(`${name}:signMessage`, this.signMessage.bind(this));
|
|
992
1020
|
this.messenger.registerActionHandler(`${name}:signEip7702Authorization`, this.signEip7702Authorization.bind(this));
|
|
993
1021
|
this.messenger.registerActionHandler(`${name}:signPersonalMessage`, this.signPersonalMessage.bind(this));
|
|
@@ -1046,70 +1074,10 @@ async function _KeyringController_createNewVaultWithKeyring(password, keyring) {
|
|
|
1046
1074
|
delete state.encryptionKey;
|
|
1047
1075
|
delete state.encryptionSalt;
|
|
1048
1076
|
});
|
|
1049
|
-
|
|
1050
|
-
ignoreExistingVault: true,
|
|
1051
|
-
});
|
|
1077
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
1052
1078
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
|
|
1053
1079
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyringWithFirstAccount).call(this, keyring.type, keyring.opts);
|
|
1054
1080
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
1055
|
-
}, _KeyringController_deriveEncryptionKey =
|
|
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 `false`, 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 use the existing vault salt and key metadata
|
|
1072
|
-
*/
|
|
1073
|
-
async function _KeyringController_deriveEncryptionKey(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");
|
|
1113
1081
|
}, _KeyringController_verifySeedPhrase =
|
|
1114
1082
|
/**
|
|
1115
1083
|
* Internal non-exclusive method to verify the seed phrase.
|
|
@@ -1190,7 +1158,7 @@ async function _KeyringController_getSerializedKeyrings({ includeUnsupported } =
|
|
|
1190
1158
|
return serializedKeyrings;
|
|
1191
1159
|
}, _KeyringController_getSessionState =
|
|
1192
1160
|
/**
|
|
1193
|
-
* Get a snapshot of session data held by
|
|
1161
|
+
* Get a snapshot of session data held by class variables.
|
|
1194
1162
|
*
|
|
1195
1163
|
* @returns An object with serialized keyrings, keyrings metadata,
|
|
1196
1164
|
* and the user password.
|
|
@@ -1198,7 +1166,7 @@ async function _KeyringController_getSerializedKeyrings({ includeUnsupported } =
|
|
|
1198
1166
|
async function _KeyringController_getSessionState() {
|
|
1199
1167
|
return {
|
|
1200
1168
|
keyrings: await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this),
|
|
1201
|
-
|
|
1169
|
+
password: __classPrivateFieldGet(this, _KeyringController_password, "f"),
|
|
1202
1170
|
};
|
|
1203
1171
|
}, _KeyringController_restoreSerializedKeyrings =
|
|
1204
1172
|
/**
|
|
@@ -1227,27 +1195,54 @@ async function _KeyringController_restoreSerializedKeyrings(serializedKeyrings)
|
|
|
1227
1195
|
* Unlock Keyrings, decrypting the vault and deserializing all
|
|
1228
1196
|
* keyrings contained in it, using a password or an encryption key with salt.
|
|
1229
1197
|
*
|
|
1230
|
-
* @param
|
|
1198
|
+
* @param password - The keyring controller password.
|
|
1199
|
+
* @param encryptionKey - An exported key string to unlock keyrings with.
|
|
1200
|
+
* @param encryptionSalt - The salt used to encrypt the vault.
|
|
1231
1201
|
* @returns A promise resolving to the deserialized keyrings array.
|
|
1232
1202
|
*/
|
|
1233
|
-
async function _KeyringController_unlockKeyrings(
|
|
1203
|
+
async function _KeyringController_unlockKeyrings(password, encryptionKey, encryptionSalt) {
|
|
1234
1204
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
|
|
1235
|
-
|
|
1205
|
+
const encryptedVault = this.state.vault;
|
|
1206
|
+
if (!encryptedVault) {
|
|
1236
1207
|
throw new Error(constants_1.KeyringControllerError.VaultError);
|
|
1237
1208
|
}
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1209
|
+
let vault;
|
|
1210
|
+
const updatedState = {};
|
|
1211
|
+
if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
|
|
1212
|
+
assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
|
|
1213
|
+
if (password) {
|
|
1214
|
+
const result = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithDetail(password, encryptedVault);
|
|
1215
|
+
vault = result.vault;
|
|
1216
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
1217
|
+
updatedState.encryptionKey = result.exportedKeyString;
|
|
1218
|
+
updatedState.encryptionSalt = result.salt;
|
|
1219
|
+
}
|
|
1220
|
+
else {
|
|
1221
|
+
const parsedEncryptedVault = JSON.parse(encryptedVault);
|
|
1222
|
+
if (encryptionSalt && encryptionSalt !== parsedEncryptedVault.salt) {
|
|
1223
|
+
throw new Error(constants_1.KeyringControllerError.ExpiredCredentials);
|
|
1224
|
+
}
|
|
1225
|
+
else {
|
|
1226
|
+
encryptionSalt = parsedEncryptedVault.salt;
|
|
1227
|
+
}
|
|
1228
|
+
if (typeof encryptionKey !== 'string') {
|
|
1229
|
+
throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
|
|
1230
|
+
}
|
|
1231
|
+
const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
|
|
1232
|
+
vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(key, parsedEncryptedVault);
|
|
1233
|
+
// This call is required on the first call because encryptionKey
|
|
1234
|
+
// is not yet inside the memStore
|
|
1235
|
+
updatedState.encryptionKey = encryptionKey;
|
|
1236
|
+
updatedState.encryptionSalt = encryptionSalt;
|
|
1237
|
+
}
|
|
1241
1238
|
}
|
|
1242
1239
|
else {
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1240
|
+
if (typeof password !== 'string') {
|
|
1241
|
+
throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
|
|
1242
|
+
}
|
|
1243
|
+
vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, encryptedVault);
|
|
1244
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
1248
1245
|
}
|
|
1249
|
-
const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
|
|
1250
|
-
const vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(key, parsedEncryptedVault);
|
|
1251
1246
|
if (!isSerializedKeyringsArray(vault)) {
|
|
1252
1247
|
throw new Error(constants_1.KeyringControllerError.VaultDataError);
|
|
1253
1248
|
}
|
|
@@ -1255,8 +1250,10 @@ async function _KeyringController_unlockKeyrings(credentials) {
|
|
|
1255
1250
|
const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
|
|
1256
1251
|
this.update((state) => {
|
|
1257
1252
|
state.keyrings = updatedKeyrings;
|
|
1258
|
-
|
|
1259
|
-
|
|
1253
|
+
if (updatedState.encryptionKey || updatedState.encryptionSalt) {
|
|
1254
|
+
state.encryptionKey = updatedState.encryptionKey;
|
|
1255
|
+
state.encryptionSalt = updatedState.encryptionSalt;
|
|
1256
|
+
}
|
|
1260
1257
|
});
|
|
1261
1258
|
return { keyrings, newMetadata };
|
|
1262
1259
|
});
|
|
@@ -1264,36 +1261,57 @@ async function _KeyringController_unlockKeyrings(credentials) {
|
|
|
1264
1261
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
|
|
1265
1262
|
// Ensure no duplicate accounts are persisted.
|
|
1266
1263
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoDuplicateAccounts).call(this);
|
|
1267
|
-
|
|
1264
|
+
const { encryptionKey, encryptionSalt, vault } = this.state;
|
|
1265
|
+
// READ THIS CAREFULLY:
|
|
1266
|
+
// We do check if the vault is still considered up-to-date, if not, we would not re-use the
|
|
1267
|
+
// cached key and we will re-generate a new one (based on the password).
|
|
1268
|
+
//
|
|
1269
|
+
// This helps doing seamless updates of the vault. Useful in case we change some cryptographic
|
|
1270
|
+
// parameters to the KDF.
|
|
1271
|
+
const useCachedKey = encryptionKey && vault && __classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated?.(vault);
|
|
1272
|
+
if (!__classPrivateFieldGet(this, _KeyringController_password, "f") && !encryptionKey) {
|
|
1268
1273
|
throw new Error(constants_1.KeyringControllerError.MissingCredentials);
|
|
1269
1274
|
}
|
|
1270
1275
|
const serializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
|
|
1271
1276
|
if (!serializedKeyrings.some((keyring) => keyring.type === KeyringTypes.hd)) {
|
|
1272
1277
|
throw new Error(constants_1.KeyringControllerError.NoHdKeyring);
|
|
1273
1278
|
}
|
|
1274
|
-
const
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1279
|
+
const updatedState = {};
|
|
1280
|
+
if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
|
|
1281
|
+
assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
|
|
1282
|
+
if (useCachedKey) {
|
|
1283
|
+
const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
|
|
1284
|
+
const vaultJSON = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithKey(key, serializedKeyrings);
|
|
1285
|
+
vaultJSON.salt = encryptionSalt;
|
|
1286
|
+
updatedState.vault = JSON.stringify(vaultJSON);
|
|
1287
|
+
}
|
|
1288
|
+
else if (__classPrivateFieldGet(this, _KeyringController_password, "f")) {
|
|
1289
|
+
const { vault: newVault, exportedKeyString } = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithDetail(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
|
|
1290
|
+
updatedState.vault = newVault;
|
|
1291
|
+
updatedState.encryptionKey = exportedKeyString;
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
else {
|
|
1295
|
+
assertIsValidPassword(__classPrivateFieldGet(this, _KeyringController_password, "f"));
|
|
1296
|
+
updatedState.vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encrypt(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
|
|
1297
|
+
}
|
|
1298
|
+
if (!updatedState.vault) {
|
|
1299
|
+
throw new Error(constants_1.KeyringControllerError.MissingVaultData);
|
|
1300
|
+
}
|
|
1285
1301
|
const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
|
|
1286
1302
|
this.update((state) => {
|
|
1287
1303
|
state.vault = updatedState.vault;
|
|
1288
1304
|
state.keyrings = updatedKeyrings;
|
|
1289
|
-
|
|
1290
|
-
|
|
1305
|
+
if (updatedState.encryptionKey) {
|
|
1306
|
+
state.encryptionKey = updatedState.encryptionKey;
|
|
1307
|
+
state.encryptionSalt = JSON.parse(updatedState.vault).salt;
|
|
1308
|
+
}
|
|
1291
1309
|
});
|
|
1292
1310
|
return true;
|
|
1293
1311
|
});
|
|
1294
1312
|
}, _KeyringController_isNewEncryptionAvailable = function _KeyringController_isNewEncryptionAvailable() {
|
|
1295
1313
|
const { vault } = this.state;
|
|
1296
|
-
if (!vault || !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated) {
|
|
1314
|
+
if (!vault || !__classPrivateFieldGet(this, _KeyringController_password, "f") || !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated) {
|
|
1297
1315
|
return false;
|
|
1298
1316
|
}
|
|
1299
1317
|
return !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated(vault);
|
|
@@ -1527,13 +1545,13 @@ async function _KeyringController_persistOrRollback(callback) {
|
|
|
1527
1545
|
async function _KeyringController_withRollback(callback) {
|
|
1528
1546
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async ({ releaseLock }) => {
|
|
1529
1547
|
const currentSerializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
|
|
1530
|
-
const
|
|
1548
|
+
const currentPassword = __classPrivateFieldGet(this, _KeyringController_password, "f");
|
|
1531
1549
|
try {
|
|
1532
1550
|
return await callback({ releaseLock });
|
|
1533
1551
|
}
|
|
1534
1552
|
catch (e) {
|
|
1535
|
-
// Keyrings and
|
|
1536
|
-
__classPrivateFieldSet(this,
|
|
1553
|
+
// Keyrings and password are restored to their previous state
|
|
1554
|
+
__classPrivateFieldSet(this, _KeyringController_password, currentPassword, "f");
|
|
1537
1555
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, currentSerializedKeyrings);
|
|
1538
1556
|
throw e;
|
|
1539
1557
|
}
|