Skip to content

Add passphrase-encrypted wallet export flow#110

Draft
fainashalts wants to merge 9 commits intomainfrom
encrypt-wallet-export
Draft

Add passphrase-encrypted wallet export flow#110
fainashalts wants to merge 9 commits intomainfrom
encrypt-wallet-export

Conversation

@fainashalts
Copy link

Add passphrase-encrypted wallet export flow

Note: this PR is generated by Cursor using Claude Opus 4.5 based on the details provided in REQ-275. This is step 1, with additional work needed in the SDK and an example to be enumerated in mono.

Summary

This PR adds a new encrypted wallet export flow that allows users to encrypt their wallet mnemonic with a passphrase before it leaves the iframe. Instead of displaying the plaintext mnemonic in the DOM, users are prompted to enter and confirm a passphrase, and the encrypted result is sent to the parent frame as base64-encoded data.

Changes

New Encryption Utilities (TKHQ Module)

  • encryptWithPassphrase(buf, passphrase) - Encrypts a Uint8Array using:

    • PBKDF2 key derivation (100,000 iterations, SHA-256)
    • AES-GCM-256 encryption
    • Returns concatenated salt (16 bytes) || iv (12 bytes) || ciphertext
  • decryptWithPassphrase(encryptedBuf, passphrase) - Decrypts data encrypted by the above function

New Message Type

  • INJECT_WALLET_EXPORT_BUNDLE_ENCRYPTED - New message type that triggers the passphrase-protected export flow instead of displaying the mnemonic directly

New UI Component

  • displayPassphraseForm(mnemonic, requestId) - Renders a form with:
    • Password input field
    • Password confirmation field
    • Validation (minimum 8 characters, passwords must match)
    • Error message display
    • "Encrypt & Export" submit button

New Output Message

  • ENCRYPTED_WALLET_EXPORT - Sent to parent frame with base64-encoded encrypted wallet data upon successful encryption

Styling

  • Added CSS styles for the passphrase form container, inputs, button, and error messages

Testing

Added 5 new tests:

  • ✅ Encrypts data with passphrase correctly
  • ✅ Decrypts data encrypted by encryptWithPassphrase correctly
  • ✅ Fails to decrypt with wrong passphrase
  • ✅ Produces different ciphertext for same plaintext (verifies random salt/IV)
  • ✅ Handles encryption of wallet mnemonic end-to-end (including base64 encoding)

All 23 tests passing.

Usage

Parent frame sends:

iframe.postMessage({
  type: "INJECT_WALLET_EXPORT_BUNDLE_ENCRYPTED",
  value: bundleString,
  organizationId: orgId,
  requestId: requestId
});

Parent frame receives (after user enters passphrase):

// On success:
{ type: "ENCRYPTED_WALLET_EXPORT", value: "<base64-encoded-encrypted-data>", requestId: "..." }

// On error:
{ type: "ERROR", value: "<error-message>", requestId: "..." }

Security Notes

  • Passphrase never leaves the iframe
  • Uses Web Crypto API for all cryptographic operations
  • PBKDF2 with 100k iterations provides reasonable protection against brute-force attacks
  • Random salt and IV ensure identical passphrases produce different ciphertexts
  • Embedded key is reset after bundle decryption (consistent with existing behavior)

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a passphrase-encrypted wallet export flow that encrypts wallet mnemonics with a user-provided passphrase before transmission from the iframe. Users enter and confirm a passphrase through a new UI form, and the encrypted data is sent to the parent frame as base64-encoded content instead of plaintext.

Key changes:

  • Implements AES-GCM-256 encryption with PBKDF2 key derivation (100,000 iterations)
  • Adds a new INJECT_WALLET_EXPORT_BUNDLE_ENCRYPTED message type and corresponding handler
  • Creates a passphrase form UI with validation (8-character minimum, matching confirmation)

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 11 comments.

File Description
export/index.template.html Adds encryption/decryption utilities, passphrase form UI with styling, and message handler for encrypted wallet export flow
export/index.test.js Adds 5 unit tests covering encryption, decryption, wrong passphrase handling, salt/IV randomness, and end-to-end base64 encoding

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

1 participant