---
id: "0150"
title: "matrix-client-pc E2EE: cross-signing, SAS verification, recovery"
status: pending
priority: critical
created: 2026-05-24
related_flows: ["0010"]
related_issues: ["0149", "0151"]
dependencies: ["0149"]
tags: [matrix, e2ee, olm, megolm, cross-signing, recovery, security]
---

## Objetivo

Encriptacion end-to-end con `mautrix-go` (Olm/Megolm). Cross-signing keys (master/self-signing/user-signing), SAS verification de devices (emoji + decimal), recovery passphrase + key backup en Synapse, manejo de devices no verificados con warning visible. Mensajes en rooms encriptados se envian y descifran correctamente.

## Tareas

1. Backend Go:
   - `MatrixService.BootstrapCrossSigning(passphrase)` — genera master/self/user keys, sube a Synapse cifradas con passphrase-derived key.
   - `MatrixService.RecoverFromPassphrase(passphrase)` — descarga keys de Synapse y descifra.
   - `MatrixService.StartVerification(userID, deviceID) -> *VerificationSession`.
   - `MatrixService.VerifyEmoji(sessionID, accepted bool)`.
   - `MatrixService.ListDevices() -> []Device` (con verified flag).
   - `MatrixService.BackupMegolmKeys()` — key backup server-side.
   - Crypto store SQLite separado del state store (mejor para integridad).
2. Frontend React:
   - Wizard onboarding E2EE: pasos (1) generar passphrase, (2) backup, (3) verificar device.
   - Panel `Settings > Security & Privacy`:
     - Lista devices propios con verified state.
     - Boton "Verify new device" + dialog SAS con emoji grid.
     - "Reset cross-signing" (destructive, requiere confirmacion).
     - "Restore from passphrase" (login en device nuevo).
   - `EventBubble` muestra shield: green (verified), amber (encrypted, device unverified), red (decryption failed).
   - Banner room: "X devices are not verified" si algun miembro tiene devices unverified.
3. Tests:
   - `e2e/test_e2ee_send_receive.sh` — msg enviado en room encriptado se descifra en Element Web.
   - `e2e/test_cross_signing.sh` — bootstrap + verificar device desde Element Web.
   - `e2e/test_recovery.sh` — login en device nuevo + recover keys con passphrase.
   - `e2e/test_unverified_warning.sh` — device nuevo aparece como warning en otros clientes.

## Funciones del registry a crear

- `matrix_e2ee_bootstrap_go_infra` — wrapper cross-signing bootstrap.
- `matrix_device_verify_go_infra` — SAS verification flow.
- `matrix_key_backup_go_infra` — server-side key backup wrapper.
- `passphrase_derive_key_go_infra` — PBKDF2/scrypt para derivar key de passphrase.
- `VerificationDialog_ts_ui` — componente emoji grid SAS.

## Acceptance

- [ ] Bootstrap cross-signing crea 3 keys + las sube a Synapse cifradas.
- [ ] Msg enviado a room encriptado se descifra en Element Web (y al reves).
- [ ] SAS verification con emoji grid funciona contra Element Web (ambos lados muestran 7 emojis iguales).
- [ ] Login en device nuevo + restore con passphrase recupera msgs historicos.
- [ ] Device no verificado dispara shield amber en EventBubble.
- [ ] Decryption failure (key no disponible) muestra shield rojo + boton "Request key".

## Notas

**Critico — anti-criterio:**
- NO marcar done si E2EE silent-falla (msg muestra "** Unable to decrypt **" sin shield rojo claro).
- NO marcar done si recovery passphrase queda en plain text en disco (debe vivir solo en keyring/memoria).

**Decisiones:**
- Olm/Megolm via `mautrix-go/crypto` (Go port estable de libolm).
- Alternativa rust-crypto via CGo: descartada, mantiene complejidad build.
- Passphrase format: 4 palabras Diceware o 12-byte base32. Usuario elige al bootstrap.

**Gotchas:**
- Key rotation: rooms encriptados rotan megolm cada 1 semana o 100 msgs (default). Manejar refresh.
- Olm sessions max 100 mensajes: rotar prekey bundles automaticamente.
- Cuando arrancas device nuevo sin passphrase, los msgs pre-existentes NO se descifran — UI debe ser clara.
