anchorage_layer_simple/userwallet/features/userwallet-iframe-key-isolation.md
ncantu f9fe0e3419 Website-skeleton partie connectée, contrat en dur, navigate-login; UserWallet pairing-relay-status, redirect; website-data, proxy data, cryptographie, fixKnowledge
**Motivations:**
- Partie connectée du skeleton accessible seulement si pairing satisfait + relais OK, avec page type skeleton (avatar, notifications).
- Éviter « Aucun service disponible » : contrat présent en dur dans la page, transmis à l’iframe ; navigation évidente ou automatique vers login.
- Sécuriser postMessage (origine UserWallet uniquement) ; déployer data sur le proxy et certificat data.certificator.4nkweb.com.
- Vulgariser cryptographie (ECDH, AES-GCM, Schnorr, workflow, collecte signatures) ; documenter correctifs et architecture.

**Root causes:**
- Section connectée affichée sans vérifier pairing/relay ; possibilité de forger pairing-relay-status depuis la console.
- Iframe masquée ou /login chargé avant réception du contrat → graphe vide, redirection vers /services.
- Pas de contrôle d’origine sur les messages reçus ; pas de projet website-data ni config Nginx/certificat pour data.

**Correctifs:**
- Vérification msg.origin === USERWALLET_ORIGIN dans handleMessage (skeleton).
- Si session mais pas pairingRelayStatus : afficher iframe pour réception du statut, message « Vérification du statut… ».
- Contrat envoyé dès load iframe (init iframe.src = USERWALLET_ORIGIN) ; au clic « Se connecter », envoi contract + navigate-login (service, membre).
- UserWallet : écoute navigate-login → navigation /login?service=&membre= ; LoginScreen avec service+membre en URL ne redirige plus vers /services, dispatch E_SELECT_SERVICE / E_SELECT_MEMBER.

**Evolutions:**
- Message pairing-relay-status (iframe → parent) ; canShowConnectedSection exige login + pairing OK + relay OK ; page connectée avec header avatar + icône notifications.
- Skeleton : getLoginContext, sendNavigateLoginToIframe, onIframeLoad, loginRequested/iframeLoaded ; contrat envoyé avec serviceUuid, membreUuid.
- UserWallet : PairingRelayStatusMessage, envoi depuis HomeScreen/LoginScreen ; type navigate-login, handleNavigateLogin dans useChannel.
- Page cryptographie.html (workflow, algorithmes, collecte signatures) ; liens nav, build.
- website-data (Vite, channel, config), start/service/install ; configure-nginx-proxy + Certbot pour data.certificator.4nkweb.com.
- fixKnowledge (postmessage-origin, section-connectee-non-affichee) ; features (partie-connectee-pairing-relay, userwallet-iframe-key-isolation).

**Pages affectées:**
- website-skeleton (index, main, config, serviceContract, cryptographie, technique, membre, contrat, vite.config, README).
- userwallet (HomeScreen, LoginScreen, useChannel, iframeChannel, relay, crypto, iframe, Pairing*, RelaySettings, WordInputGrid, syncUpdateGraph, specs/synthese).
- website-data (nouveau), configure-nginx-proxy, docs DOMAINS_AND_PORTS README, features, fixKnowledge, userwallet features/docs.
2026-01-29 00:55:58 +01:00

2.5 KiB
Raw Blame History

UserWallet iframe — cloisonnement des clés et du chiffrement

Objectif

Garantir quaucune clé secrète ne quitte liframe UserWallet et quaucune opération de signature ou de chiffrement nest effectuée en dehors du domaine de liframe.

Règles

  1. Clés

    • Seules les clés publiques peuvent sortir de liframe (via postMessage vers le parent).
    • Les clés privées (privateKey, cle_privee) ne doivent jamais être envoyées au parent ni à un autre domaine.
  2. Crypto

    • Toutes les opérations de signature, chiffrement et déchiffrement sont réalisées uniquement dans liframe (UserWallet).
    • Le parent (site intégrateur, ex. skeleton) ne doit jamais signer, chiffrer ni déchiffrer. Il peut uniquement vérifier des signatures à laide des clés publiques (ex. verifyLoginProof).

Implémentation

  • iframeChannel : sendToChannel appelle assertNoSecretsInChannelPayload avant postMessage. Toute présence de privateKey ou cle_privee dans le payload (récursif) lève une erreur ; le message nest pas envoyé.
  • iframe.ts : sendMessageToParent appelle aussi assertNoSecretsInChannelPayload sur le payload avant postMessage. Tous les envois vers le parent passent par cette vérification.
  • Messages envoyés au parent : auth-response (signature, publicKey, message), login-proof (challenge, signatures avec cle_publique), error, service-status, pairing-relay-status (pairingSatisfied, relayOk). Aucun de ces messages ne contient de clé secrète.
  • Messages reçus du parent : auth-request, contract. Le contrat peut contenir des cle_publique de service (validateurs) ; ce sont des clés publiques. Le parent nenvoie jamais de clé privée.
  • Parent (intégrateur) : Ne doit jamais signer, chiffrer ni déchiffrer. Il peut uniquement vérifier des signatures (ex. verifyLoginProof avec clés publiques). Ex. skeleton : vérification uniquement, pas de crypto secrète.

Contrôles

  • Avant tout envoi vers le parent : vérification systématique des payloads pour privateKey et cle_privee.
  • Aucun usage de privateKey / cle_privee dans les types de messages définis pour le canal iframe (AuthResponseMessage, LoginProofMessage, etc.).

Pages affectées

  • userwallet/src/utils/iframeChannel.ts (assertion, sendToChannel)
  • userwallet/src/utils/iframe.ts (assertion, sendMessageToParent)
  • userwallet/features/userwallet-iframe-key-isolation.md (ce document)