@metamask-previews/keyring-controller 24.0.0-preview-7b44fb9a → 24.0.0-preview-e958bbad
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 +20 -0
- package/dist/KeyringController.cjs +119 -138
- package/dist/KeyringController.cjs.map +1 -1
- package/dist/KeyringController.d.cts +52 -34
- package/dist/KeyringController.d.cts.map +1 -1
- package/dist/KeyringController.d.mts +52 -34
- package/dist/KeyringController.d.mts.map +1 -1
- package/dist/KeyringController.mjs +120 -139
- package/dist/KeyringController.mjs.map +1 -1
- package/dist/constants.cjs +1 -0
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +1 -0
- package/dist/constants.d.cts.map +1 -1
- package/dist/constants.d.mts +1 -0
- package/dist/constants.d.mts.map +1 -1
- package/dist/constants.mjs +1 -0
- package/dist/constants.mjs.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,26 @@ 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 ([#5963](https://github.com/MetaMask/core/pull/5963))
|
|
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 ([#5963](https://github.com/MetaMask/core/pull/5963))
|
|
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 ([#5963](https://github.com/MetaMask/core/pull/5963))
|
|
20
|
+
|
|
21
|
+
### Removed
|
|
22
|
+
|
|
23
|
+
- **BREAKING:** The `cacheEncryptionKey` parameter has been removed from the `KeyringController` constructor options ([#5963](https://github.com/MetaMask/core/pull/5963))
|
|
24
|
+
- 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.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- Fixed incorrect type for `decryptWithKey` method of `ExportableKeyEncryptor` ([#5963](https://github.com/MetaMask/core/pull/5963))
|
|
29
|
+
|
|
10
30
|
## [24.0.0]
|
|
11
31
|
|
|
12
32
|
### Changed
|
|
@@ -36,12 +36,11 @@ 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,
|
|
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_deriveEncryptionKey, _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");
|
|
43
43
|
const base_controller_1 = require("@metamask/base-controller");
|
|
44
|
-
const encryptorUtils = __importStar(require("@metamask/browser-passworder"));
|
|
45
44
|
const eth_hd_keyring_1 = require("@metamask/eth-hd-keyring");
|
|
46
45
|
const eth_sig_util_1 = require("@metamask/eth-sig-util");
|
|
47
46
|
const eth_simple_keyring_1 = __importDefault(require("@metamask/eth-simple-keyring"));
|
|
@@ -136,23 +135,6 @@ function assertHasUint8ArrayMnemonic(keyring) {
|
|
|
136
135
|
throw new Error("Can't get mnemonic bytes from keyring");
|
|
137
136
|
}
|
|
138
137
|
}
|
|
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
|
-
}
|
|
156
138
|
/**
|
|
157
139
|
* Assert that the provided password is a valid non-empty string.
|
|
158
140
|
*
|
|
@@ -254,12 +236,11 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
254
236
|
* @param options - Initial options used to configure this controller
|
|
255
237
|
* @param options.encryptor - An optional object for defining encryption schemes.
|
|
256
238
|
* @param options.keyringBuilders - Set a new name for account.
|
|
257
|
-
* @param options.cacheEncryptionKey - Whether to cache or not encryption key.
|
|
258
239
|
* @param options.messenger - A restricted messenger.
|
|
259
240
|
* @param options.state - Initial state to set on this controller.
|
|
260
241
|
*/
|
|
261
242
|
constructor(options) {
|
|
262
|
-
const { encryptor
|
|
243
|
+
const { encryptor, keyringBuilders, messenger, state } = options;
|
|
263
244
|
super({
|
|
264
245
|
name,
|
|
265
246
|
metadata: {
|
|
@@ -305,22 +286,15 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
305
286
|
_KeyringController_vaultOperationMutex.set(this, new async_mutex_1.Mutex());
|
|
306
287
|
_KeyringController_keyringBuilders.set(this, void 0);
|
|
307
288
|
_KeyringController_encryptor.set(this, void 0);
|
|
308
|
-
_KeyringController_cacheEncryptionKey.set(this, void 0);
|
|
309
289
|
_KeyringController_keyrings.set(this, void 0);
|
|
310
290
|
_KeyringController_unsupportedKeyrings.set(this, void 0);
|
|
311
|
-
|
|
291
|
+
_KeyringController_encryptionKey.set(this, void 0);
|
|
312
292
|
__classPrivateFieldSet(this, _KeyringController_keyringBuilders, keyringBuilders
|
|
313
293
|
? keyringBuilders.concat(defaultKeyringBuilders)
|
|
314
294
|
: defaultKeyringBuilders, "f");
|
|
315
295
|
__classPrivateFieldSet(this, _KeyringController_encryptor, encryptor, "f");
|
|
316
296
|
__classPrivateFieldSet(this, _KeyringController_keyrings, [], "f");
|
|
317
297
|
__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
|
-
}
|
|
324
298
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_registerMessageHandlers).call(this);
|
|
325
299
|
}
|
|
326
300
|
/**
|
|
@@ -691,7 +665,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
691
665
|
async setLocked() {
|
|
692
666
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
|
|
693
667
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
694
|
-
__classPrivateFieldSet(this,
|
|
668
|
+
__classPrivateFieldSet(this, _KeyringController_encryptionKey, undefined, "f");
|
|
695
669
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
|
|
696
670
|
this.update((state) => {
|
|
697
671
|
state.isUnlocked = false;
|
|
@@ -873,22 +847,11 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
873
847
|
*/
|
|
874
848
|
changePassword(password) {
|
|
875
849
|
__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
|
-
}
|
|
880
850
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
|
|
881
851
|
assertIsValidPassword(password);
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
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
|
-
}
|
|
852
|
+
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveEncryptionKey).call(this, password, {
|
|
853
|
+
ignoreExistingVault: true,
|
|
854
|
+
});
|
|
892
855
|
});
|
|
893
856
|
}
|
|
894
857
|
/**
|
|
@@ -897,12 +860,15 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
897
860
|
* consistency with the vault salt.
|
|
898
861
|
*
|
|
899
862
|
* @param encryptionKey - Key to unlock the keychain.
|
|
900
|
-
* @param
|
|
863
|
+
* @param keyDerivationSalt - Optional salt to unlock the keychain.
|
|
901
864
|
* @returns Promise resolving when the operation completes.
|
|
902
865
|
*/
|
|
903
|
-
async submitEncryptionKey(encryptionKey,
|
|
866
|
+
async submitEncryptionKey(encryptionKey, keyDerivationSalt) {
|
|
904
867
|
const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
905
|
-
const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this,
|
|
868
|
+
const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, {
|
|
869
|
+
encryptionKey,
|
|
870
|
+
keyDerivationSalt,
|
|
871
|
+
});
|
|
906
872
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
907
873
|
return result;
|
|
908
874
|
});
|
|
@@ -929,9 +895,8 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
929
895
|
async exportEncryptionKey() {
|
|
930
896
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
|
|
931
897
|
return await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async () => {
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
return encryptionKey;
|
|
898
|
+
assertIsEncryptionKeySet(__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")?.serialized);
|
|
899
|
+
return __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").serialized;
|
|
935
900
|
});
|
|
936
901
|
}
|
|
937
902
|
/**
|
|
@@ -943,7 +908,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
943
908
|
*/
|
|
944
909
|
async submitPassword(password) {
|
|
945
910
|
const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
946
|
-
const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, password);
|
|
911
|
+
const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, { password });
|
|
947
912
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
948
913
|
return result;
|
|
949
914
|
});
|
|
@@ -953,6 +918,12 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
953
918
|
// can attempt to upgrade the vault.
|
|
954
919
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
955
920
|
if (newMetadata || __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isNewEncryptionAvailable).call(this)) {
|
|
921
|
+
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveEncryptionKey).call(this, password, {
|
|
922
|
+
// If the vault is being upgraded, we want to ignore the metadata
|
|
923
|
+
// that is already in the vault, so we can effectively
|
|
924
|
+
// re-encrypt the vault with the new encryption config.
|
|
925
|
+
ignoreExistingVault: true,
|
|
926
|
+
});
|
|
956
927
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
|
|
957
928
|
}
|
|
958
929
|
});
|
|
@@ -1015,7 +986,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
1015
986
|
}
|
|
1016
987
|
}
|
|
1017
988
|
exports.KeyringController = KeyringController;
|
|
1018
|
-
_KeyringController_controllerOperationMutex = new WeakMap(), _KeyringController_vaultOperationMutex = new WeakMap(), _KeyringController_keyringBuilders = new WeakMap(), _KeyringController_encryptor = new WeakMap(),
|
|
989
|
+
_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() {
|
|
1019
990
|
this.messenger.registerActionHandler(`${name}:signMessage`, this.signMessage.bind(this));
|
|
1020
991
|
this.messenger.registerActionHandler(`${name}:signEip7702Authorization`, this.signEip7702Authorization.bind(this));
|
|
1021
992
|
this.messenger.registerActionHandler(`${name}:signPersonalMessage`, this.signPersonalMessage.bind(this));
|
|
@@ -1074,10 +1045,70 @@ async function _KeyringController_createNewVaultWithKeyring(password, keyring) {
|
|
|
1074
1045
|
delete state.encryptionKey;
|
|
1075
1046
|
delete state.encryptionSalt;
|
|
1076
1047
|
});
|
|
1077
|
-
|
|
1048
|
+
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveEncryptionKey).call(this, password, {
|
|
1049
|
+
ignoreExistingVault: true,
|
|
1050
|
+
});
|
|
1078
1051
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
|
|
1079
1052
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyringWithFirstAccount).call(this, keyring.type, keyring.opts);
|
|
1080
1053
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
1054
|
+
}, _KeyringController_deriveEncryptionKey =
|
|
1055
|
+
/**
|
|
1056
|
+
* Derive the vault encryption key from the provided password, and
|
|
1057
|
+
* assign it to the instance variable for later use with cryptographic
|
|
1058
|
+
* functions.
|
|
1059
|
+
*
|
|
1060
|
+
* When the controller has a vault in its state, the key is derived
|
|
1061
|
+
* using the salt from the vault. If the vault is empty, a new salt
|
|
1062
|
+
* is generated and used to derive the key.
|
|
1063
|
+
*
|
|
1064
|
+
* If `options.ignoreExistingVault` is set to `false`, the existing
|
|
1065
|
+
* vault is completely ignored: the new key won't be able to decrypt
|
|
1066
|
+
* the existing vault, and should be used to re-encrypt it.
|
|
1067
|
+
*
|
|
1068
|
+
* @param password - The password to use for decryption or derivation.
|
|
1069
|
+
* @param options - Options for the key derivation.
|
|
1070
|
+
* @param options.ignoreExistingVault - Whether to use the existing vault salt and key metadata
|
|
1071
|
+
*/
|
|
1072
|
+
async function _KeyringController_deriveEncryptionKey(password, options = {
|
|
1073
|
+
ignoreExistingVault: false,
|
|
1074
|
+
}) {
|
|
1075
|
+
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
|
|
1076
|
+
const { vault } = this.state;
|
|
1077
|
+
if (typeof password !== 'string') {
|
|
1078
|
+
throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
|
|
1079
|
+
}
|
|
1080
|
+
let serializedEncryptionKey, salt;
|
|
1081
|
+
if (vault && !options.ignoreExistingVault) {
|
|
1082
|
+
// The `decryptWithDetail` method is being used here instead of
|
|
1083
|
+
// `keyFromPassword` + `exportKey` to let the encryptor handle
|
|
1084
|
+
// any legacy encryption formats and metadata that might be
|
|
1085
|
+
// present (or absent) in the vault.
|
|
1086
|
+
const { exportedKeyString, salt: existingSalt } = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithDetail(password, vault);
|
|
1087
|
+
serializedEncryptionKey = exportedKeyString;
|
|
1088
|
+
salt = existingSalt;
|
|
1089
|
+
}
|
|
1090
|
+
else {
|
|
1091
|
+
salt = __classPrivateFieldGet(this, _KeyringController_encryptor, "f").generateSalt();
|
|
1092
|
+
serializedEncryptionKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").exportKey(await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").keyFromPassword(password, salt, true));
|
|
1093
|
+
}
|
|
1094
|
+
__classPrivateFieldSet(this, _KeyringController_encryptionKey, {
|
|
1095
|
+
salt,
|
|
1096
|
+
serialized: serializedEncryptionKey,
|
|
1097
|
+
}, "f");
|
|
1098
|
+
}, _KeyringController_setEncryptionKey = function _KeyringController_setEncryptionKey(encryptionKey, keyDerivationSalt) {
|
|
1099
|
+
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
|
|
1100
|
+
if (typeof encryptionKey !== 'string' ||
|
|
1101
|
+
typeof keyDerivationSalt !== 'string') {
|
|
1102
|
+
throw new TypeError(constants_1.KeyringControllerError.WrongEncryptionKeyType);
|
|
1103
|
+
}
|
|
1104
|
+
const { vault } = this.state;
|
|
1105
|
+
if (vault && JSON.parse(vault).salt !== keyDerivationSalt) {
|
|
1106
|
+
throw new Error(constants_1.KeyringControllerError.ExpiredCredentials);
|
|
1107
|
+
}
|
|
1108
|
+
__classPrivateFieldSet(this, _KeyringController_encryptionKey, {
|
|
1109
|
+
salt: keyDerivationSalt,
|
|
1110
|
+
serialized: encryptionKey,
|
|
1111
|
+
}, "f");
|
|
1081
1112
|
}, _KeyringController_verifySeedPhrase =
|
|
1082
1113
|
/**
|
|
1083
1114
|
* Internal non-exclusive method to verify the seed phrase.
|
|
@@ -1158,7 +1189,7 @@ async function _KeyringController_getSerializedKeyrings({ includeUnsupported } =
|
|
|
1158
1189
|
return serializedKeyrings;
|
|
1159
1190
|
}, _KeyringController_getSessionState =
|
|
1160
1191
|
/**
|
|
1161
|
-
* Get a snapshot of session data held by
|
|
1192
|
+
* Get a snapshot of session data held by instance variables.
|
|
1162
1193
|
*
|
|
1163
1194
|
* @returns An object with serialized keyrings, keyrings metadata,
|
|
1164
1195
|
* and the user password.
|
|
@@ -1166,7 +1197,7 @@ async function _KeyringController_getSerializedKeyrings({ includeUnsupported } =
|
|
|
1166
1197
|
async function _KeyringController_getSessionState() {
|
|
1167
1198
|
return {
|
|
1168
1199
|
keyrings: await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this),
|
|
1169
|
-
|
|
1200
|
+
encryptionKey: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f"),
|
|
1170
1201
|
};
|
|
1171
1202
|
}, _KeyringController_restoreSerializedKeyrings =
|
|
1172
1203
|
/**
|
|
@@ -1195,54 +1226,27 @@ async function _KeyringController_restoreSerializedKeyrings(serializedKeyrings)
|
|
|
1195
1226
|
* Unlock Keyrings, decrypting the vault and deserializing all
|
|
1196
1227
|
* keyrings contained in it, using a password or an encryption key with salt.
|
|
1197
1228
|
*
|
|
1198
|
-
* @param
|
|
1199
|
-
* @param encryptionKey - An exported key string to unlock keyrings with.
|
|
1200
|
-
* @param encryptionSalt - The salt used to encrypt the vault.
|
|
1229
|
+
* @param credentials - The credentials to unlock the keyrings.
|
|
1201
1230
|
* @returns A promise resolving to the deserialized keyrings array.
|
|
1202
1231
|
*/
|
|
1203
|
-
async function _KeyringController_unlockKeyrings(
|
|
1232
|
+
async function _KeyringController_unlockKeyrings(credentials) {
|
|
1204
1233
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
|
|
1205
|
-
|
|
1206
|
-
if (!encryptedVault) {
|
|
1234
|
+
if (!this.state.vault) {
|
|
1207
1235
|
throw new Error(constants_1.KeyringControllerError.VaultError);
|
|
1208
1236
|
}
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
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
|
-
}
|
|
1237
|
+
const parsedEncryptedVault = JSON.parse(this.state.vault);
|
|
1238
|
+
if ('password' in credentials) {
|
|
1239
|
+
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveEncryptionKey).call(this, credentials.password);
|
|
1238
1240
|
}
|
|
1239
1241
|
else {
|
|
1240
|
-
|
|
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");
|
|
1242
|
+
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setEncryptionKey).call(this, credentials.encryptionKey, credentials.keyDerivationSalt || parsedEncryptedVault.salt);
|
|
1245
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);
|
|
1246
1250
|
if (!isSerializedKeyringsArray(vault)) {
|
|
1247
1251
|
throw new Error(constants_1.KeyringControllerError.VaultDataError);
|
|
1248
1252
|
}
|
|
@@ -1250,10 +1254,8 @@ async function _KeyringController_unlockKeyrings(password, encryptionKey, encryp
|
|
|
1250
1254
|
const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
|
|
1251
1255
|
this.update((state) => {
|
|
1252
1256
|
state.keyrings = updatedKeyrings;
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
state.encryptionSalt = updatedState.encryptionSalt;
|
|
1256
|
-
}
|
|
1257
|
+
state.encryptionKey = encryptionKey;
|
|
1258
|
+
state.encryptionSalt = parsedEncryptedVault.salt;
|
|
1257
1259
|
});
|
|
1258
1260
|
return { keyrings, newMetadata };
|
|
1259
1261
|
});
|
|
@@ -1261,57 +1263,36 @@ async function _KeyringController_unlockKeyrings(password, encryptionKey, encryp
|
|
|
1261
1263
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
|
|
1262
1264
|
// Ensure no duplicate accounts are persisted.
|
|
1263
1265
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoDuplicateAccounts).call(this);
|
|
1264
|
-
|
|
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) {
|
|
1266
|
+
if (!__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")) {
|
|
1273
1267
|
throw new Error(constants_1.KeyringControllerError.MissingCredentials);
|
|
1274
1268
|
}
|
|
1275
1269
|
const serializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
|
|
1276
1270
|
if (!serializedKeyrings.some((keyring) => keyring.type === KeyringTypes.hd)) {
|
|
1277
1271
|
throw new Error(constants_1.KeyringControllerError.NoHdKeyring);
|
|
1278
1272
|
}
|
|
1279
|
-
const
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
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
|
-
}
|
|
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
|
+
};
|
|
1301
1284
|
const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
|
|
1302
1285
|
this.update((state) => {
|
|
1303
1286
|
state.vault = updatedState.vault;
|
|
1304
1287
|
state.keyrings = updatedKeyrings;
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
state.encryptionSalt = JSON.parse(updatedState.vault).salt;
|
|
1308
|
-
}
|
|
1288
|
+
state.encryptionKey = updatedState.encryptionKey;
|
|
1289
|
+
state.encryptionSalt = updatedState.encryptionSalt;
|
|
1309
1290
|
});
|
|
1310
1291
|
return true;
|
|
1311
1292
|
});
|
|
1312
1293
|
}, _KeyringController_isNewEncryptionAvailable = function _KeyringController_isNewEncryptionAvailable() {
|
|
1313
1294
|
const { vault } = this.state;
|
|
1314
|
-
if (!vault || !__classPrivateFieldGet(this,
|
|
1295
|
+
if (!vault || !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated) {
|
|
1315
1296
|
return false;
|
|
1316
1297
|
}
|
|
1317
1298
|
return !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated(vault);
|
|
@@ -1545,13 +1526,13 @@ async function _KeyringController_persistOrRollback(callback) {
|
|
|
1545
1526
|
async function _KeyringController_withRollback(callback) {
|
|
1546
1527
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async ({ releaseLock }) => {
|
|
1547
1528
|
const currentSerializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
|
|
1548
|
-
const
|
|
1529
|
+
const currentEncryptionKey = (0, lodash_1.cloneDeep)(__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f"));
|
|
1549
1530
|
try {
|
|
1550
1531
|
return await callback({ releaseLock });
|
|
1551
1532
|
}
|
|
1552
1533
|
catch (e) {
|
|
1553
|
-
// Keyrings and
|
|
1554
|
-
__classPrivateFieldSet(this,
|
|
1534
|
+
// Keyrings and encryption credentials are restored to their previous state
|
|
1535
|
+
__classPrivateFieldSet(this, _KeyringController_encryptionKey, currentEncryptionKey, "f");
|
|
1555
1536
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, currentSerializedKeyrings);
|
|
1556
1537
|
throw e;
|
|
1557
1538
|
}
|