@metamask-previews/keyring-controller 24.0.0-preview-4419d7e4 → 24.0.0-preview-c2c8112b
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 -20
- package/dist/KeyringController.cjs +138 -107
- package/dist/KeyringController.cjs.map +1 -1
- package/dist/KeyringController.d.cts +33 -41
- package/dist/KeyringController.d.cts.map +1 -1
- package/dist/KeyringController.d.mts +33 -41
- package/dist/KeyringController.d.mts.map +1 -1
- package/dist/KeyringController.mjs +139 -108
- 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 +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,26 +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` and `SupportedKeyDerivationOptions` type parameters to the `KeyringController`, `ExportableKeyEncryptor` and `KeyringControllerOptions` types ([#5963](https://github.com/MetaMask/core/pull/5963))
|
|
13
|
-
- This type parameter allows specifying the key derivation options supported by the injected encryptor, defaulting to `@metamask/browser-passworder` types.
|
|
14
|
-
|
|
15
|
-
### Changed
|
|
16
|
-
|
|
17
|
-
- **BREAKING:** The `KeyringController` constructor now requires an encryptor supporting the `keyFromPassword`, `exportKey` and `generateSalt` methods ([#5963](https://github.com/MetaMask/core/pull/5963))
|
|
18
|
-
- The `encryptor` constructor option was previously optional and defaulted to an instance of `@metamask/browser-passworder`.
|
|
19
|
-
|
|
20
|
-
### Removed
|
|
21
|
-
|
|
22
|
-
- **BREAKING:** The `cacheEncryptionKey` parameter has been removed from the `KeyringController` constructor options ([#5963](https://github.com/MetaMask/core/pull/5963))
|
|
23
|
-
- 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.
|
|
24
|
-
- **BREAKING:** The `GenericEncryptor` type has been removed ([#5963](https://github.com/MetaMask/core/pull/5963))
|
|
25
|
-
|
|
26
|
-
### Fixed
|
|
27
|
-
|
|
28
|
-
- Fixed incorrect type for `decryptWithKey` method of `ExportableKeyEncryptor` ([#5963](https://github.com/MetaMask/core/pull/5963))
|
|
29
|
-
|
|
30
10
|
## [24.0.0]
|
|
31
11
|
|
|
32
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
|
*
|
|
@@ -236,11 +254,12 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
236
254
|
* @param options - Initial options used to configure this controller
|
|
237
255
|
* @param options.encryptor - An optional object for defining encryption schemes.
|
|
238
256
|
* @param options.keyringBuilders - Set a new name for account.
|
|
257
|
+
* @param options.cacheEncryptionKey - Whether to cache or not encryption key.
|
|
239
258
|
* @param options.messenger - A restricted messenger.
|
|
240
259
|
* @param options.state - Initial state to set on this controller.
|
|
241
260
|
*/
|
|
242
261
|
constructor(options) {
|
|
243
|
-
const { encryptor, keyringBuilders, messenger, state } = options;
|
|
262
|
+
const { encryptor = encryptorUtils, keyringBuilders, messenger, state, } = options;
|
|
244
263
|
super({
|
|
245
264
|
name,
|
|
246
265
|
metadata: {
|
|
@@ -286,15 +305,22 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
286
305
|
_KeyringController_vaultOperationMutex.set(this, new async_mutex_1.Mutex());
|
|
287
306
|
_KeyringController_keyringBuilders.set(this, void 0);
|
|
288
307
|
_KeyringController_encryptor.set(this, void 0);
|
|
308
|
+
_KeyringController_cacheEncryptionKey.set(this, void 0);
|
|
289
309
|
_KeyringController_keyrings.set(this, void 0);
|
|
290
310
|
_KeyringController_unsupportedKeyrings.set(this, void 0);
|
|
291
|
-
|
|
311
|
+
_KeyringController_password.set(this, void 0);
|
|
292
312
|
__classPrivateFieldSet(this, _KeyringController_keyringBuilders, keyringBuilders
|
|
293
313
|
? keyringBuilders.concat(defaultKeyringBuilders)
|
|
294
314
|
: defaultKeyringBuilders, "f");
|
|
295
315
|
__classPrivateFieldSet(this, _KeyringController_encryptor, encryptor, "f");
|
|
296
316
|
__classPrivateFieldSet(this, _KeyringController_keyrings, [], "f");
|
|
297
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
|
+
}
|
|
298
324
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_registerMessageHandlers).call(this);
|
|
299
325
|
}
|
|
300
326
|
/**
|
|
@@ -665,7 +691,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
665
691
|
async setLocked() {
|
|
666
692
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
|
|
667
693
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
668
|
-
__classPrivateFieldSet(this,
|
|
694
|
+
__classPrivateFieldSet(this, _KeyringController_password, undefined, "f");
|
|
669
695
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
|
|
670
696
|
this.update((state) => {
|
|
671
697
|
state.isUnlocked = false;
|
|
@@ -847,9 +873,22 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
847
873
|
*/
|
|
848
874
|
changePassword(password) {
|
|
849
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
|
+
}
|
|
850
880
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
|
|
851
881
|
assertIsValidPassword(password);
|
|
852
|
-
|
|
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
|
+
}
|
|
853
892
|
});
|
|
854
893
|
}
|
|
855
894
|
/**
|
|
@@ -858,15 +897,12 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
858
897
|
* consistency with the vault salt.
|
|
859
898
|
*
|
|
860
899
|
* @param encryptionKey - Key to unlock the keychain.
|
|
861
|
-
* @param
|
|
900
|
+
* @param encryptionSalt - Optional salt to unlock the keychain.
|
|
862
901
|
* @returns Promise resolving when the operation completes.
|
|
863
902
|
*/
|
|
864
|
-
async submitEncryptionKey(encryptionKey,
|
|
903
|
+
async submitEncryptionKey(encryptionKey, encryptionSalt) {
|
|
865
904
|
const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
866
|
-
const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this,
|
|
867
|
-
encryptionKey,
|
|
868
|
-
keyDerivationSalt,
|
|
869
|
-
});
|
|
905
|
+
const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, undefined, encryptionKey, encryptionSalt);
|
|
870
906
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
871
907
|
return result;
|
|
872
908
|
});
|
|
@@ -893,8 +929,9 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
893
929
|
async exportEncryptionKey() {
|
|
894
930
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
|
|
895
931
|
return await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async () => {
|
|
896
|
-
|
|
897
|
-
|
|
932
|
+
const { encryptionKey } = this.state;
|
|
933
|
+
assertIsEncryptionKeySet(encryptionKey);
|
|
934
|
+
return encryptionKey;
|
|
898
935
|
});
|
|
899
936
|
}
|
|
900
937
|
/**
|
|
@@ -906,7 +943,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
906
943
|
*/
|
|
907
944
|
async submitPassword(password) {
|
|
908
945
|
const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
909
|
-
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);
|
|
910
947
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
911
948
|
return result;
|
|
912
949
|
});
|
|
@@ -916,12 +953,6 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
916
953
|
// can attempt to upgrade the vault.
|
|
917
954
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
|
|
918
955
|
if (newMetadata || __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isNewEncryptionAvailable).call(this)) {
|
|
919
|
-
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveEncryptionKey).call(this, password, {
|
|
920
|
-
// If the vault is being upgraded, we want to ignore the metadata
|
|
921
|
-
// that is already in the vault, so we can effectively
|
|
922
|
-
// re-encrypt the vault with the new encryption config.
|
|
923
|
-
useVaultKeyMetadata: false,
|
|
924
|
-
});
|
|
925
956
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
|
|
926
957
|
}
|
|
927
958
|
});
|
|
@@ -984,7 +1015,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
984
1015
|
}
|
|
985
1016
|
}
|
|
986
1017
|
exports.KeyringController = KeyringController;
|
|
987
|
-
_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() {
|
|
988
1019
|
this.messenger.registerActionHandler(`${name}:signMessage`, this.signMessage.bind(this));
|
|
989
1020
|
this.messenger.registerActionHandler(`${name}:signEip7702Authorization`, this.signEip7702Authorization.bind(this));
|
|
990
1021
|
this.messenger.registerActionHandler(`${name}:signPersonalMessage`, this.signPersonalMessage.bind(this));
|
|
@@ -1043,60 +1074,10 @@ async function _KeyringController_createNewVaultWithKeyring(password, keyring) {
|
|
|
1043
1074
|
delete state.encryptionKey;
|
|
1044
1075
|
delete state.encryptionSalt;
|
|
1045
1076
|
});
|
|
1046
|
-
|
|
1077
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
1047
1078
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
|
|
1048
1079
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyringWithFirstAccount).call(this, keyring.type, keyring.opts);
|
|
1049
1080
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
1050
|
-
}, _KeyringController_deriveEncryptionKey =
|
|
1051
|
-
/**
|
|
1052
|
-
* Derive the vault encryption key from the provided password, and
|
|
1053
|
-
* assign it to the instance variable for later use with cryptographic
|
|
1054
|
-
* functions.
|
|
1055
|
-
*
|
|
1056
|
-
* When the controller has a vault in its state, the key is derived
|
|
1057
|
-
* using the salt from the vault. If the vault is empty, a new salt
|
|
1058
|
-
* is generated and used to derive the key.
|
|
1059
|
-
*
|
|
1060
|
-
* @param password - The password to use for decryption or derivation.
|
|
1061
|
-
* @param options - Options for the key derivation.
|
|
1062
|
-
* @param options.useVaultKeyMetadata - Whether to use the vault key metadata
|
|
1063
|
-
*/
|
|
1064
|
-
async function _KeyringController_deriveEncryptionKey(password, options = {
|
|
1065
|
-
useVaultKeyMetadata: true,
|
|
1066
|
-
}) {
|
|
1067
|
-
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
|
|
1068
|
-
const { vault } = this.state;
|
|
1069
|
-
if (typeof password !== 'string') {
|
|
1070
|
-
throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
|
|
1071
|
-
}
|
|
1072
|
-
let salt, keyMetadata;
|
|
1073
|
-
if (vault && options.useVaultKeyMetadata) {
|
|
1074
|
-
const parsedVault = JSON.parse(vault);
|
|
1075
|
-
salt = parsedVault.salt;
|
|
1076
|
-
keyMetadata = parsedVault.keyMetadata;
|
|
1077
|
-
}
|
|
1078
|
-
else {
|
|
1079
|
-
salt = __classPrivateFieldGet(this, _KeyringController_encryptor, "f").generateSalt();
|
|
1080
|
-
}
|
|
1081
|
-
const serializedEncryptionKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").exportKey(await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").keyFromPassword(password, salt, true, keyMetadata));
|
|
1082
|
-
__classPrivateFieldSet(this, _KeyringController_encryptionKey, {
|
|
1083
|
-
salt,
|
|
1084
|
-
serialized: serializedEncryptionKey,
|
|
1085
|
-
}, "f");
|
|
1086
|
-
}, _KeyringController_setEncryptionKey = function _KeyringController_setEncryptionKey(encryptionKey, keyDerivationSalt) {
|
|
1087
|
-
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
|
|
1088
|
-
if (typeof encryptionKey !== 'string' ||
|
|
1089
|
-
typeof keyDerivationSalt !== 'string') {
|
|
1090
|
-
throw new TypeError(constants_1.KeyringControllerError.WrongEncryptionKeyType);
|
|
1091
|
-
}
|
|
1092
|
-
const { vault } = this.state;
|
|
1093
|
-
if (vault && JSON.parse(vault).salt !== keyDerivationSalt) {
|
|
1094
|
-
throw new Error(constants_1.KeyringControllerError.ExpiredCredentials);
|
|
1095
|
-
}
|
|
1096
|
-
__classPrivateFieldSet(this, _KeyringController_encryptionKey, {
|
|
1097
|
-
salt: keyDerivationSalt,
|
|
1098
|
-
serialized: encryptionKey,
|
|
1099
|
-
}, "f");
|
|
1100
1081
|
}, _KeyringController_verifySeedPhrase =
|
|
1101
1082
|
/**
|
|
1102
1083
|
* Internal non-exclusive method to verify the seed phrase.
|
|
@@ -1177,7 +1158,7 @@ async function _KeyringController_getSerializedKeyrings({ includeUnsupported } =
|
|
|
1177
1158
|
return serializedKeyrings;
|
|
1178
1159
|
}, _KeyringController_getSessionState =
|
|
1179
1160
|
/**
|
|
1180
|
-
* Get a snapshot of session data held by
|
|
1161
|
+
* Get a snapshot of session data held by class variables.
|
|
1181
1162
|
*
|
|
1182
1163
|
* @returns An object with serialized keyrings, keyrings metadata,
|
|
1183
1164
|
* and the user password.
|
|
@@ -1185,7 +1166,7 @@ async function _KeyringController_getSerializedKeyrings({ includeUnsupported } =
|
|
|
1185
1166
|
async function _KeyringController_getSessionState() {
|
|
1186
1167
|
return {
|
|
1187
1168
|
keyrings: await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this),
|
|
1188
|
-
|
|
1169
|
+
password: __classPrivateFieldGet(this, _KeyringController_password, "f"),
|
|
1189
1170
|
};
|
|
1190
1171
|
}, _KeyringController_restoreSerializedKeyrings =
|
|
1191
1172
|
/**
|
|
@@ -1214,27 +1195,54 @@ async function _KeyringController_restoreSerializedKeyrings(serializedKeyrings)
|
|
|
1214
1195
|
* Unlock Keyrings, decrypting the vault and deserializing all
|
|
1215
1196
|
* keyrings contained in it, using a password or an encryption key with salt.
|
|
1216
1197
|
*
|
|
1217
|
-
* @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.
|
|
1218
1201
|
* @returns A promise resolving to the deserialized keyrings array.
|
|
1219
1202
|
*/
|
|
1220
|
-
async function _KeyringController_unlockKeyrings(
|
|
1203
|
+
async function _KeyringController_unlockKeyrings(password, encryptionKey, encryptionSalt) {
|
|
1221
1204
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
|
|
1222
|
-
|
|
1205
|
+
const encryptedVault = this.state.vault;
|
|
1206
|
+
if (!encryptedVault) {
|
|
1223
1207
|
throw new Error(constants_1.KeyringControllerError.VaultError);
|
|
1224
1208
|
}
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
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
|
+
}
|
|
1228
1238
|
}
|
|
1229
1239
|
else {
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
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");
|
|
1235
1245
|
}
|
|
1236
|
-
const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
|
|
1237
|
-
const vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(key, parsedEncryptedVault);
|
|
1238
1246
|
if (!isSerializedKeyringsArray(vault)) {
|
|
1239
1247
|
throw new Error(constants_1.KeyringControllerError.VaultDataError);
|
|
1240
1248
|
}
|
|
@@ -1242,8 +1250,10 @@ async function _KeyringController_unlockKeyrings(credentials) {
|
|
|
1242
1250
|
const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
|
|
1243
1251
|
this.update((state) => {
|
|
1244
1252
|
state.keyrings = updatedKeyrings;
|
|
1245
|
-
|
|
1246
|
-
|
|
1253
|
+
if (updatedState.encryptionKey || updatedState.encryptionSalt) {
|
|
1254
|
+
state.encryptionKey = updatedState.encryptionKey;
|
|
1255
|
+
state.encryptionSalt = updatedState.encryptionSalt;
|
|
1256
|
+
}
|
|
1247
1257
|
});
|
|
1248
1258
|
return { keyrings, newMetadata };
|
|
1249
1259
|
});
|
|
@@ -1251,36 +1261,57 @@ async function _KeyringController_unlockKeyrings(credentials) {
|
|
|
1251
1261
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
|
|
1252
1262
|
// Ensure no duplicate accounts are persisted.
|
|
1253
1263
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoDuplicateAccounts).call(this);
|
|
1254
|
-
|
|
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) {
|
|
1255
1273
|
throw new Error(constants_1.KeyringControllerError.MissingCredentials);
|
|
1256
1274
|
}
|
|
1257
1275
|
const serializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
|
|
1258
1276
|
if (!serializedKeyrings.some((keyring) => keyring.type === KeyringTypes.hd)) {
|
|
1259
1277
|
throw new Error(constants_1.KeyringControllerError.NoHdKeyring);
|
|
1260
1278
|
}
|
|
1261
|
-
const
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
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
|
+
}
|
|
1272
1301
|
const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
|
|
1273
1302
|
this.update((state) => {
|
|
1274
1303
|
state.vault = updatedState.vault;
|
|
1275
1304
|
state.keyrings = updatedKeyrings;
|
|
1276
|
-
|
|
1277
|
-
|
|
1305
|
+
if (updatedState.encryptionKey) {
|
|
1306
|
+
state.encryptionKey = updatedState.encryptionKey;
|
|
1307
|
+
state.encryptionSalt = JSON.parse(updatedState.vault).salt;
|
|
1308
|
+
}
|
|
1278
1309
|
});
|
|
1279
1310
|
return true;
|
|
1280
1311
|
});
|
|
1281
1312
|
}, _KeyringController_isNewEncryptionAvailable = function _KeyringController_isNewEncryptionAvailable() {
|
|
1282
1313
|
const { vault } = this.state;
|
|
1283
|
-
if (!vault || !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated) {
|
|
1314
|
+
if (!vault || !__classPrivateFieldGet(this, _KeyringController_password, "f") || !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated) {
|
|
1284
1315
|
return false;
|
|
1285
1316
|
}
|
|
1286
1317
|
return !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated(vault);
|
|
@@ -1514,13 +1545,13 @@ async function _KeyringController_persistOrRollback(callback) {
|
|
|
1514
1545
|
async function _KeyringController_withRollback(callback) {
|
|
1515
1546
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async ({ releaseLock }) => {
|
|
1516
1547
|
const currentSerializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
|
|
1517
|
-
const
|
|
1548
|
+
const currentPassword = __classPrivateFieldGet(this, _KeyringController_password, "f");
|
|
1518
1549
|
try {
|
|
1519
1550
|
return await callback({ releaseLock });
|
|
1520
1551
|
}
|
|
1521
1552
|
catch (e) {
|
|
1522
|
-
// Keyrings and
|
|
1523
|
-
__classPrivateFieldSet(this,
|
|
1553
|
+
// Keyrings and password are restored to their previous state
|
|
1554
|
+
__classPrivateFieldSet(this, _KeyringController_password, currentPassword, "f");
|
|
1524
1555
|
await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, currentSerializedKeyrings);
|
|
1525
1556
|
throw e;
|
|
1526
1557
|
}
|