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 :
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
// 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 / option | Rô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)
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ête | Contenu |
|---|---|
X-Aub-Chiffre | aes-256-gcm |
X-Aub-Cle | la clé, base64 de 32 octets (au hasard, par envoi) |
X-Aub-Iv | l’IV, base64 de 12 octets (au hasard, par requête) |
X-Aub-Envoi | facultatif : encodeURIComponent(JSON) des infos de l’envoi (n° du morceau, nom…) |
| Corps | chiffré ‖ étiquette GCM (16 octets), tel que le rend WebCrypto |
- ✔ 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.