Skip to content

Support Multi-srp backups in SeedlessOnboardingController #5685

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 11 commits into
base: feat/seedless-onboarding-controller
Choose a base branch
from

Conversation

lwin-kyaw
Copy link

@lwin-kyaw lwin-kyaw commented Apr 22, 2025

Explanation

Support multiple SeedPhrases backup under one user account (social).

  • Added addNewSeedPhraseBackup in controller to create backup for new SeedPhrase.
  • Added EncryptionKey (which will be derived from the password) in the controller as non-persisted state, to unlock the Seedless Vault to retrieve the Encryption Key and Auth Key without entering the password. The reason for storing this is that when user imports new SeedPhrase in the wallet, the newly imported SeedPhrase can be backed up automatically without needing to type the password.
  • Added Controller Lock and sync with KeyringController:lock and KeyringController:unlock events

References

Changelog

@metamask/seedless-onboarding-controller

  • ADDED: added addNewSeedPhraseBackup method in the controller to use for import new SeedPhrase
  • UPDATED: updated Encryptor interface with the ExportableKeyEncryptor from KeyringController
  • ADDED: encryptionKey and encryptionSalt state as non-persisted state
  • ADDED: lock to sync with KeyringController's lock and unlock events
  • UPDATED: Order of restored SeedPhrases from the fetchAllSeedPhrases method to be the same order as KeyringsMetadata from KeyringController
  • ADDED: helper methods to check/assert Controller Lock state
  • UPDATED: mark encryptor as required property in SeedlessOnboardingControllerOptions

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed, highlighting breaking changes as necessary
  • I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes

* @param password - The password to verify.
* @throws {Error} If the password is invalid or the vault is not initialized.
*/
async #verifyPassword(password: string) {

Choose a reason for hiding this comment

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

Suggested change
async #verifyPassword(password: string) {
async #verifyVaultPassword(password: string) {

@@ -94,6 +130,8 @@ export class SeedlessOnboardingController extends BaseController<

readonly toprfClient: ToprfSecureBackup;

#password?: string;

Choose a reason for hiding this comment

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

why are we storing password here? Does keyring controller also does this?

}
await this.#vaultEncryptor.decrypt(password, this.state.vault);
}

/**
* Unlocks the encrypted vault using the provided password and returns the decrypted vault data.
* This method ensures thread-safety by using a mutex lock when accessing the vault.

Choose a reason for hiding this comment

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

Function description needs to be updated since we don't provide password anymore as arg

@@ -423,25 +492,58 @@ export class SeedlessOnboardingController extends BaseController<
* - The password is incorrect (from encryptor.decrypt)
* - The decrypted vault data is malformed
*/
async #unlockVaultWithPassword(password: string): Promise<{
async #unlockVaultAndGetBackupEncKey(): Promise<{

Choose a reason for hiding this comment

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

it would be rather better to have password as optional param here, rather thn loading it from state inside the function

});

this.#password = password;

Choose a reason for hiding this comment

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

since we are setting vaultEncryptionKey above, do we really need to set password as well in class variable, wht the case when vaultEncryptionKey might be missing but password would be required instead?

encryptedString: EncryptionResult,
) => Promise<unknown>;
/**
* Generates an encryption key from exported key string.

Choose a reason for hiding this comment

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

Suggested change
* Generates an encryption key from exported key string.
* Generates an encryption key from imported key string.

/**
* Generates an encryption key from exported key string.
*
* @param key - The exported key string.

Choose a reason for hiding this comment

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

Suggested change
* @param key - The exported key string.
* @param key - The imported key string.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants