Skip to content
This repository was archived by the owner on Oct 7, 2024. It is now read-only.

Add encryptor types #293

Merged
merged 17 commits into from
Nov 14, 2023
Merged

Add encryptor types #293

merged 17 commits into from
Nov 14, 2023

Conversation

mikesposito
Copy link
Member

@mikesposito mikesposito commented Nov 7, 2023

Description

Currently encryptor type is any, and as different clients can use different encryptor utilities, we need to establish a minimum supported (or needed) interface that the encryptor should implement.

This PR adds some types and guards to the encryptor, taking into account @metamask/browser-passworder, which is the encryptor used by the extension, and the Encryptor class used by mobile

Restrictions have also been added for cacheEncryptionKey and encryptor, as the methods that the encryptor must support depends on whether we need the encryption key to be exported or not. To do this, public class variables have been substituted with sharp vars and a check on construction has been added: an error is thrown when they are incompatible

Changes

  • BREAKING: encryptor class variable is now inaccessible
  • BREAKING: cacheEncryptionKey class variable is now inaccessible
  • BREAKING: encryptor constructor option type has been changed to GenericEncryptor | ExportableKeyEncryptor | undefined

References

Waiting on MetaMask/browser-passworder#49

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation for new or updated code as appropriate (note: this will usually be JSDoc)
  • I've highlighted breaking changes using the "BREAKING" category above as appropriate

Comment on lines 945 to 947
if (this.cacheEncryptionKey) {
assertIsKeyEncryptor(encryptor);
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't cache the encryption key if the provided encryptor does not support it

@mikesposito mikesposito marked this pull request as ready for review November 10, 2023 10:40
@mikesposito mikesposito requested a review from a team as a code owner November 10, 2023 10:40
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mikesposito mikesposito force-pushed the refactor/add-encryptor-types branch 2 times, most recently from 6655146 to 848eb83 Compare November 10, 2023 12:08
@legobeat
Copy link
Contributor

Would be nice if we can get out #290 before this is merged.

@mikesposito mikesposito requested a review from Gudahtt November 13, 2023 10:34
Comment on lines -392 to -332
expect(initialMemStore.encryptionKey).toBeUndefined();
expect(initialMemStore.encryptionSalt).toBeUndefined();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are not applicable anymore, as cacheEncryptionKey is set to true on construction (before the first createNewVaultAndKeychain > persistAllKeyrings is called), so encryptionKey and encryptionSalt will be already defined

@mikesposito mikesposito force-pushed the refactor/add-encryptor-types branch from 960c02c to aff13b0 Compare November 13, 2023 14:13
Gudahtt
Gudahtt previously approved these changes Nov 13, 2023
Copy link
Member

@Gudahtt Gudahtt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few pending suggestions/questions but overall this LGTM!

key,
serializedKeyrings,
);
vaultJSON.salt = encryptionSalt;
if (encryptionSalt) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Hmm, this should always exist if encryptionKey exists. Maybe there's a way to make that more clear using types.

Copy link
Member Author

@mikesposito mikesposito Nov 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the KeyringControllerState type to:

export type KeyringControllerState = {
  keyrings: KeyringObject[];
  isUnlocked: boolean;
} & (
  | { encryptionKey: string; encryptionSalt: string }
  | {
      encryptionKey?: never;
      encryptionSalt?: never;
    }
);

Is there a better way to represent this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also enforce the right encryptor type doing something similar on KeyringControllerArgs:

export type KeyringControllerArgs = {
  keyringBuilders?: { (): Keyring<Json>; type: string }[];
  initState?: KeyringControllerPersistentState;
} & (
  | { encryptor?: ExportableKeyEncryptor; cacheEncryptionKey: true }
  | {
      encryptor?: GenericEncryptor | ExportableKeyEncryptor;
      cacheEncryptionKey: false;
    }
);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Looks reasonable

if (
this.password &&
this.#encryptor.updateVault &&
(await this.#encryptor.updateVault(encryptedVault, this.password)) !==
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: most of the work this function is doing (the encryption) is being thrown away here. Maybe we can come back to this an optimize this by having it just check whether the vault is outdated or not instead (e.g. expose isVaultUpdated, or inline that logic here).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's quite bad. The best way would be to expose isVaultUpdated from browser-passworder, because I don't think there's a nice way to inline that logic here, as eth-keyring-controller would have to know the latest vault parameters (DEFAULT_DERIVATION_PARAMS in browser-passworder, which is also not exposed)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, good point. Maybe something to address in a follow up PR then

mcmire
mcmire previously approved these changes Nov 13, 2023
Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had some nits as well, but this makes sense and looks good.

Co-authored-by: Elliot Winkler <elliot.winkler@gmail.com>
@mikesposito mikesposito dismissed stale reviews from mcmire and Gudahtt via 1de36a5 November 14, 2023 09:21
@mikesposito mikesposito force-pushed the refactor/add-encryptor-types branch from bb102b7 to e3a3545 Compare November 14, 2023 11:21
Copy link
Member

@Gudahtt Gudahtt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@mikesposito mikesposito merged commit 75b4893 into main Nov 14, 2023
@mikesposito mikesposito deleted the refactor/add-encryptor-types branch November 14, 2023 12:58
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

encryptor lacks sufficient typing
4 participants