Support

Chiffrement de bout en bout (E2EE)

MorisBox chiffre le contenu in-app afin que les serveurs ne stockent que le ciphertext et les métadonnées. Les clés privées ne quittent jamais les appareils utilisateur ou agent.

Ce qui est chiffré

ContenuE2EE
Conversations support (utilisateur ↔ agents partenaire)Oui
Messages hub marqués encryption: "e2e"Oui
Médias dans les enveloppes E2EOui
Corps OTP / SMS / repli WhatsAppNon (doivent être lisibles sur ces canaux)
Métadonnées (partenaire, horodatages, état, taille)Non

Les messages E2E stockent le contenu uniquement in-app. Si l'utilisateur n'est pas en ligne dans l'app (aucune activité appareil depuis ~5 minutes), MorisBox envoie aussi une alerte opaque WhatsApp (puis SMS) :

Nouveau message de {partner} dans votre boîte MorisBox. Ouvrez l’app pour le lire (message sécurisé).

Cette alerte n'inclut jamais le corps chiffré. Les codes OTP et de connexion ne sont pas E2EE afin que les utilisateurs puissent toujours accéder à leur compte.

Protocole (v1)

ÉlémentAlgorithme
Identité appareilX25519
Accord de cléECDH (X25519)
KDFHKDF-SHA-256
Chiffrement du contenuAES-256-GCM
Encodage filaireBase64url
content_key  →  AES-GCM encrypt(plaintext JSON)
wrap(content_key) per recipient device via ECDH + AES-GCM

Le double ratchet de style Signal n'est pas en v1 (durcissement prévu).

Annuaire de clés appareil

Appareils utilisateur

Après connexion, le client génère une paire de clés d'identité et publie la moitié publique :

POST /api/v1/me/devices/keys
Authorization: Bearer <user_jwt>
Content-Type: application/json

{
  "identity_key_pub": "<b64url x25519 public key>"
}

Appareils agent partenaire (Partner Hub)

POST /api/v1/agent/devices/keys
Authorization: Bearer <partner_api_key>

{
  "device_uuid": "<browser session uuid>",
  "identity_key_pub": "<b64url>"
}

Récupérer les clés pour un téléphone

GET /api/v1/keys/+228XXXXXXXX
Authorization: Bearer <partner_api_key>
{
  "phone": "+228XXXXXXXX",
  "devices": [
    {
      "device_uuid": "...",
      "identity_key_pub": "...",
      "platform": "web",
      "has_keys": true
    }
  ],
  "agent_devices": [ ... ]
}

Envoyer un message hub chiffré

POST /api/v1/messages
Authorization: Bearer <partner_api_key>
Content-Type: application/json

{
  "phone": "+228XXXXXXXX",
  "encryption": "e2e",
  "e2e_envelope": {
    "v": 1,
    "alg": "x25519-hkdf-sha256-aes-256-gcm",
    "mode": "sealed",
    "key_version": 0,
    "sender_device_uuid": "partner-agent-…",
    "ciphertext": "<b64url>",
    "nonce": "<b64url>",
    "aad": "seed360|msg|<ref>|v1",
    "key_wraps": [
      {
        "device_uuid": "user-device-…",
        "wrap": "<b64url>",
        "wrap_nonce": "<b64url>",
        "sender_eph_pub": "<b64url>"
      }
    ]
  },
  "content_type": "text"
}

Le serveur stocke uniquement l'enveloppe. body n'est jamais persisté en clair.

Erreurs :

CodeSignification
e2e_no_devicesL'utilisateur n'a pas encore publié de clés d'identité
validatione2e_envelope.ciphertext / nonce manquant

Messages de conversation (client)

POST /api/v1/me/conversations/<ref>/messages
Authorization: Bearer <user_jwt>

{
  "encrypted": true,
  "e2e_mode": "conversation",
  "e2e_key_version": 3,
  "e2e_envelope": { ... }
}

Uploader les wraps de content-key :

POST /api/v1/me/conversations/<ref>/keys
{
  "key_version": 3,
  "wraps": [
    {
      "device_uuid": "...",
      "device_kind": "user",
      "wrap": "...",
      "wrap_nonce": "...",
      "sender_eph_pub": "..."
    }
  ]
}

Annuaire des pairs :

GET /api/v1/me/conversations/<ref>/devices

Comportement client

ClientComportement
Application Client / MobileGénérer les clés à la connexion ; chiffrer le chat ; déchiffrer les enveloppes pour l'affichage
Partner HubPublier les clés agent ; chiffrer les réponses / envois hub scellés
ServeurRoute le ciphertext ; ne déchiffre jamais

L'UI affiche un libellé cadenas sur les messages chiffrés. Si cet appareil n'a pas de wrap, l'utilisateur voit « impossible de déchiffrer ».

Notes de sécurité

  • Les clés privées restent sur l'appareil (SecureStore / stockage local ; durcir vers des clés matérielles lorsque disponible).
  • L'AAD lie l'enveloppe à une chaîne de contexte message pour réduire les attaques par substitution.
  • Les appareils révoqués sont exclus des nouveaux wraps.
  • Ne journalisez pas les corps déchiffrés sur les serveurs ou passerelles.

Voir aussi