Aller au contenu
Aubui · Envoi chiffré
Composants

Envoi chiffréNouveau

AubuiEnvoi envoie un fichier sans qu’il soit jamais lisible sur le disque du serveur, même un instant. Le navigateur chiffre chaque morceau (AES-256-GCM, une clé au hasard par fichier), le serveur le déchiffre en mémoire et le range aussitôt à sa place — chiffré au repos si sa destination l’est. Sans chiffrement possible, rien ne part. Premiers usages : Drive (tous les envois) et Gestion (documents des papiers).

Pourquoi

PHP range tout corps de requête de plus de 16 Ko dans un fichier temporaire du serveur avant même de le traiter : les fichiers d’un formulaire (multipart) comme un corps brut. TLS protège le trajet, pas ce fichier. Avec AubuiEnvoi, ce fichier temporaire ne contient plus que du chiffré : la clé et l’IV voyagent dans des en-têtes, qui restent en mémoire.

Essayer

Ce navigateur sait-il chiffrer ? …

C’est le composant réel : il chiffre le premier morceau de ton fichier (1 Mo au plus) et te montre ce qui partirait. Rien n’est envoyé depuis cette page.

Installer

Rien dans aubui.js : la page qui envoie charge le composant à la demande (≈ 2 Ko compressé, gardé un an en cache), à la version d’Aubui, au premier envoi :

JS
function envoiPret() {
  if (window.AubuiEnvoi) return Promise.resolve(window.AubuiEnvoi);
  return new Promise(function (ok, ko) {
    var s = document.createElement('script');
    s.src = 'https://ui.aubota.xyz/js/aubui-envoi.js?v=' + ((window.Aubui && Aubui.build) || '0');
    s.onload = function () { window.AubuiEnvoi ? ok(window.AubuiEnvoi) : ko(new Error('chiffre')); };
    s.onerror = function () { ko(new Error('Envoi indisponible : recharge la page.')); };
    document.head.appendChild(s);
  });
}

API window.AubuiEnvoi

JS
// un fichier entier, par morceaux de 1 Mo (un seul en mémoire à la fois), reprise et nouveaux essais compris
AubuiEnvoi.fichier('/api/envoi', fichier, {
  morceau: 1048576,
  entetes: { 'X-Gestion-Token': jeton },
  meta: function (i, total) { return { uid: uid, index: i, total: total, taille: fichier.size, nom: fichier.name }; },
  deja: [0, 1],                               // morceaux déjà reçus (reprise après coupure)
  progres: function (fait, total) { barre.value = 100 * fait / total; },
  definitif: function (j) { return j.code === 'csrf'; }   // inutile de réessayer
}).then(function (j) { /* réponse du dernier morceau (j.fini, j.item…) */ });

// une seule requête (une image du scanner, un petit fichier)
AubuiEnvoi.envoyer(url, blob, { entetes: {…}, meta: {…}, session: AubuiEnvoi.session() }).then(function (r) { return r.json(); });

// seulement chiffrer (le corps et les en-têtes à mettre dans ta requête)
AubuiEnvoi.chiffrer(blob, session).then(function (ch) { /* ch.corps (ArrayBuffer), ch.entetes */ });

if (!AubuiEnvoi.disponible()) AubuiEnvoi.refuser();   // dialogue Aubui : « Envoi chiffré impossible »
Méthode / optionRôle
disponible()true si la page est en https (ou localhost) et que le navigateur a WebCrypto.
session()Un objet à passer d’un appel à l’autre : une clé pour tout l’envoi (créée au premier usage, non exportable), un IV neuf à chaque requête.
chiffrer(donnees, session?)Blob / File / tranche, ArrayBuffer, Uint8Array ou texte → {corps, entetes}. Rejeté avec err.code = 'chiffre' sans WebCrypto.
envoyer(url, donnees, o)POST du corps chiffré ; o.entetes, o.meta (→ en-tête X-Aub-Envoi, JSON encodé), o.session, o.methode, o.signal. Rend la Response.
fichier(url, f, o)Morceaux l’un après l’autre (léger en 3G/4G). o.morceau, o.meta(i, total), o.deja, o.essais (5), o.lire(r), o.definitif(j), o.progres(fait, total, j), o.essai(n, err), o.fini(j) (défaut : j.fini). Rejeté avec l’erreur du serveur (err.code, err.reponse).
refuser(message?)Le dit avec AubuiDialog.alert (jamais de popup native).

Côté serveur (PHP)

PHP
require_once '…/src.aubota.xyz/php/core/EnvoiChiffre.php';
if (!EnvoiChiffre::present()) { /* refus « recharge la page » (400, code chiffre) */ }
$c = EnvoiChiffre::corps(4194304, 'Morceau');   // [ok, octets] ou [ok:false, code, erreur] — déchiffré EN MÉMOIRE
$m = EnvoiChiffre::meta();                        // le contenu de X-Aub-Envoi
// puis on l’écrit directement à sa place : DriveStore::recevoirOctets(…) (chiffré au repos si la destination l’est,
// ChiffreRepos::chiffrerOctetsVers / assemblerVers) — jamais de copie en clair en plus
En-têteContenu
X-Aub-Chiffreaes-256-gcm
X-Aub-Clela clé, base64 de 32 octets (au hasard, par envoi)
X-Aub-Ivl’IV, base64 de 12 octets (au hasard, par requête)
X-Aub-Envoifacultatif : encodeURIComponent(JSON) des infos de l’envoi (n° du morceau, nom…)
Corpschiffré ‖ étiquette GCM (16 octets), tel que le rend WebCrypto
Ce que ça protège, et ce que ça ne protège pas
  • ✔ Le disque du serveur : fichiers temporaires de PHP et du serveur web, morceaux d’un envoi en cours.
  • ✘ Pas un chiffrement « de bout en bout » : le serveur reçoit la clé (dans l’en-tête) pour lire et ranger le fichier. TLS protège déjà le trajet.
  • Le fichier rangé est chiffré au repos seulement là où sa destination l’est (Drive › Gestion, papiers) ; ailleurs dans le Drive, il est rangé comme avant.
Aubui · design system AUBOTA · version 2026-10-31-4 · API figée · README · Une nouveauté Aubui = une section ici.