mChat English Ouvrir mChat

mChat · document

Chiffrer depuis votre propre code

Le SDK tourne chez vous, dans le navigateur ou sous Node. Le relais transporte des enveloppes qu'il ne peut pas ouvrir. Il n'y a rien à installer et aucune clé d'API à demander.

01

Il n'existe aucune route qui chiffre

C'est volontaire, et c'est la seule décision de conception qui compte ici. Une route qui chiffre reçoit votre message en clair : le serveur pourrait le lire, donc le conserver, donc être contraint de le remettre. Appeler /api/v1/chiffrer rend un 410 qui redit cette phrase, parce que c'est la première adresse que tout le monde essaie.

02

Sceller un message

Le SDK s'importe directement depuis le domaine, sans rien installer : tout ce qu'il utilise est servi avec lui. Sous Node, importez plutôt /sdk/mchat.mjs, qui garde ses dépendances en spécificateurs nus.

// navigateur : rien a installer, aucune cle d'API
import { genererIdentite, sceller, ouvrir }
  from 'https://medchat.medcode.ca/sdk/mchat.web.mjs';

const bob = genererIdentite();

// On scelle avec les cles PUBLIQUES du destinataire
const enveloppe = sceller(bob.publiques, 'Le code est 4417');

// Lui seul peut ouvrir
ouvrir(bob.privees, bob.publiques, enveloppe);
// -> 'Le code est 4417'
03

Ce que fait le sceau

Une paire X25519 éphémère, jetée aussitôt, plus une encapsulation ML-KEM-768 vers la clé du destinataire. La clé de chiffrement dérive des deux secrets à la fois et se referme sur ChaCha20-Poly1305. Il faut casser les deux moitiés : l'une tient contre les ordinateurs d'aujourd'hui, l'autre contre ceux d'après.

04

Sous Node

Les primitives sont des paquets publics : installez-les une fois, récupérez le SDK à côté, et le même code tourne sans navigateur. C'est la forme à spécificateurs nus qu'il faut ici, pas celle du web.

npm i @noble/curves @noble/post-quantum \
      @noble/ciphers @noble/hashes
curl -O https://medchat.medcode.ca/sdk/mchat.mjs
05

Déposer et relever, en vrai

Relever sa file demande une signature ed25519 sur une chaîne précise. C'est la seule partie où l'on peut se tromper en silence : une signature mal formée rend 403 sans dire laquelle des deux moitiés est fausse.

import { genererIdentite, sceller, ouvrir } from './mchat.mjs';
import { ed25519 } from '@noble/curves/ed25519.js';

const API = 'https://medchat.medcode.ca';
const post = (c, b) => fetch(API + c, { method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify(b) }).then(r => r.json());

const moi = genererIdentite();
await post('/api/v1/identite', { nom: 'mon_service', publiques: moi.publiques });

// ecrire a quelqu'un
const { publiques } = await fetch(API + '/api/v1/identite/bob').then(r => r.json());
await post('/api/v1/relai', { pour: 'bob', enveloppe: sceller(publiques, 'salut') });

// relever SA file : signature obligatoire
const ts = Math.floor(Date.now() / 1000);
const msg = new TextEncoder().encode(`mchat-api|relever|mon_service|${ts}`);
const sig = Buffer.from(
  ed25519.sign(msg, Buffer.from(moi.privees.sig, 'base64'))).toString('hex');

const { enveloppes } = await post('/api/v1/relever', { nom: 'mon_service', ts, sig });
for (const e of enveloppes) console.log(ouvrir(moi.privees, moi.publiques, e));
06

Le sceau n'authentifie pas l'expéditeur

N'importe qui connaissant une clé publique peut sceller un message pour elle : c'est la propriété d'une boîte scellée, pas un défaut. Si votre destinataire doit savoir de qui vient le message, signez le clair avant de le sceller.

const sig = signer(alice.privees, message);
const env = sceller(bob.publiques, JSON.stringify({ message, sig }));

// chez Bob
verifier(alice.publiques, message, sig); // true
07

Publier ses clés et relever son courrier

Le relais est facultatif : vous pouvez transporter les enveloppes par vos propres moyens. Si vous vous en servez, relever sa file exige une signature, sinon connaître un nom suffirait pour vider la boîte de quelqu'un d'autre.

// resume des routes
// publier ses cles PUBLIQUES sous un nom
POST /api/v1/identite      { nom, publiques }
GET  /api/v1/identite/:nom

// deposer et relever
POST /api/v1/relai         { pour, enveloppe }
POST /api/v1/relever       { nom, ts, sig }

// sig = ed25519 sur : mchat-api|relever|<nom>|<ts>
// ts en secondes, fenetre de 120 s
08

Les limites, écrites d'avance

Une enveloppe fait au plus 64 Kio et une file au plus 200 enveloppes en attente : au-delà le dépôt est refusé avec un 429 plutôt que de faire tomber le service. Les files sont écrites sur disque et survivent au redémarrage ; une enveloppe non relevée après 30 jours est jetée. Un nom déjà pris ne se réécrit pas sans la clé qui l'a publié.