Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 11, 2025

Overview

This PR implements end-to-end encryption features for ADHD Chat, following the Matrix E2E encryption specification. Users can now generate encryption keys through a guided setup flow and enable encryption on a per-room basis.

Changes

User-Facing Features

1. Encryption Setup Wizard

A multi-step modal flow guides users through setting up E2E encryption:

  • Generate: Creates a recovery key using matrix-js-sdk's createRecoveryKeyFromPassphrase()
  • Display & Save: Shows the recovery key with a copy button and security warning
  • Verify: Requires users to re-enter the key to confirm they saved it correctly
  • Success: Confirms encryption setup is complete

2. Home Page Integration

Added a dedicated "Encryption" section with:

  • Clear explanation of E2E encryption benefits
  • "Generate Encryption Key" button to launch the setup wizard
  • Integration with existing authentication flow

3. Room-Level Encryption Controls

Enhanced room pages to show:

  • Visual encryption status indicator (✓ Encrypted / Not encrypted)
  • "Enable Encryption" button for unencrypted rooms
  • Warning that encryption cannot be disabled once enabled
  • Proper error handling for encryption enablement failures

Technical Implementation

New Components:

  • Modal.tsx - Reusable modal with keyboard support (ESC to close), backdrop overlay, and size variants
  • EncryptionSetupModal.tsx - Multi-step wizard with validation, error handling, and clipboard integration

Updated Components:

  • useMatrixClient.ts - Modified handleSetupEncryption() to properly return the generated recovery key and handle errors
  • Home.tsx - Added encryption section and modal integration
  • Room.tsx - Added encryption status checking and enablement via m.room.encryption state events

Matrix SDK Integration:

Follows matrix-js-sdk best practices for E2E encryption:

  • Uses existing initRustCrypto() initialization
  • Implements bootstrapSecretStorage() with recovery key generation
  • Configures bootstrapCrossSigning() for device verification
  • Automatically sets up key backup via resetKeyBackup()
  • Sends m.room.encryption state events with m.megolm.v1.aes-sha2 algorithm

Security Considerations

  • Recovery keys are securely generated using matrix-js-sdk cryptographic functions
  • Users must explicitly save and verify their recovery key before proceeding
  • Clear warnings emphasize the importance of storing keys safely
  • Encryption is irreversible once enabled in a room (as per Matrix spec)
  • Keys are stored in IndexedDB via the Rust crypto WASM implementation

Screenshots

Login Page

Login Page

E2E Encryption Features

E2E Encryption Features

The screenshot above demonstrates all encryption UI components including the setup wizard flow (generate, display, verify, success) and room encryption controls.

Documentation

Added comprehensive ENCRYPTION_FEATURES.md documenting:

  • Complete feature descriptions and user flows
  • Technical implementation details
  • Matrix SDK integration approach
  • Security considerations
  • Future enhancement suggestions

Testing

  • ✅ TypeScript compilation passes
  • ✅ Linting passes
  • ✅ Build successful
  • ✅ UI components follow existing design patterns

References

Fixes #[issue_number]

Original prompt

This section details on the original issue you should resolve

<issue_title>E2E encryption</issue_title>
<issue_description>Enable e2e encryption

Guide here: https://matrix.org/docs/matrix-concepts/end-to-end-encryption/

Use the matrix-js-sdk to allow the user to enable e2e encryption for their device.

A user should have an option to enable e2e encryption in specific rooms.

A user should be able to click a button "generate encryption key". This should open a modal where a user will be presented their encryption keys, be told to save them somewhere safe, then "continue" where then will then be asked to re-enter their encryption key.

Be sure to reference the guide from matrix-js-sdk (the following is copy and paste from their readme).

End-to-end encryption support

matrix-js-sdk's end-to-end encryption support is based on the WebAssembly bindings of the Rust matrix-sdk-crypto library.
Initialization

To initialize the end-to-end encryption support in the matrix client:

// Create a new matrix client
const matrixClient = sdk.createClient({
baseUrl: "http://localhost:8008",
accessToken: myAccessToken,
userId: myUserId,
});

// Initialize to enable end-to-end encryption support.
await matrixClient.initRustCrypto();

Note that by default it will attempt to use the Indexed DB provided by the browser as a crypto store. If running outside the browser, you will need to pass an options object which includes useIndexedDB: false, to use an ephemeral in-memory store instead. Note that without a persistent store, you'll need to create a new device on the server side (with MatrixClient.loginRequest) each time your application starts.

After calling initRustCrypto, you can obtain a reference to the CryptoApi interface, which is the main entry point for end-to-end encryption, by calling MatrixClient.getCrypto.

WARNING: the cryptography stack is not thread-safe. Having multiple MatrixClient instances connected to the same Indexed DB will cause data corruption and decryption failures. The application layer is responsible for ensuring that only one MatrixClient issue is instantiated at a time.
Secret storage

You should normally set up secret storage before using the end-to-end encryption. To do this, call CryptoApi.bootstrapSecretStorage. bootstrapSecretStorage can be called unconditionally: it will only set up the secret storage if it is not already set up (unless you use the setupNewSecretStorage parameter).

const matrixClient = sdk.createClient({
...,
cryptoCallbacks: {
getSecretStorageKey: async (keys) => {
// This function should prompt the user to enter their secret storage key.
return mySecretStorageKeys;
},
},
});

matrixClient.getCrypto().bootstrapSecretStorage({
// This function will be called if a new secret storage key (aka recovery key) is needed.
// You should prompt the user to save the key somewhere, because they will need it to unlock secret storage in future.
createSecretStorageKey: async () => {
return mySecretStorageKey;
},
});

The example above will create a new secret storage key if secret storage was not previously set up. The secret storage data will be encrypted using the secret storage key returned in createSecretStorageKey.

We recommend that you prompt the user to re-enter this key when CryptoCallbacks.getSecretStorageKey is called (when the secret storage access is needed).
Set up cross-signing

To set up cross-signing to verify devices and other users, call CryptoApi.bootstrapCrossSigning:

matrixClient.getCrypto().bootstrapCrossSigning({
authUploadDeviceSigningKeys: async (makeRequest) => {
return makeRequest(authDict);
},
});

The authUploadDeviceSigningKeys callback is required in order to upload newly-generated public cross-signing keys to the server.
Ke...

Fixes #8


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copy link

netlify bot commented Oct 11, 2025

Deploy Preview for tandem-chat ready!

Name Link
🔨 Latest commit 3d6042c
🔍 Latest deploy log https://app.netlify.com/projects/tandem-chat/deploys/68ea815a41fb0a0008728a54
😎 Deploy Preview https://deploy-preview-9--tandem-chat.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copilot AI and others added 2 commits October 11, 2025 16:05
Co-authored-by: coder13 <881394+coder13@users.noreply.github.com>
Co-authored-by: coder13 <881394+coder13@users.noreply.github.com>
@Copilot Copilot AI changed the title [WIP] Add support for end-to-end encryption in rooms Add E2E encryption setup UI and room-level encryption controls Oct 11, 2025
@Copilot Copilot AI requested a review from coder13 October 11, 2025 16:11
Copilot finished work on behalf of coder13 October 11, 2025 16:11
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.

E2E encryption

2 participants