counted

← Tous les guides

Comment Counted chiffre un compte partagé quand le lien est la clé

Chaque projet Counted a une clé aléatoire de 32 octets, rangée dans le fragment de l'URL, que les navigateurs n'envoient jamais à un serveur. Tout ce que vous saisissez est chiffré sur l'appareil avec XChaCha20-Poly1305 avant de partir. Les comptes sont facultatifs ; avec un compte, le mot de passe ne quitte jamais l'appareil non plus. Le client est sous licence AGPL et se reconstruit à l'identique, donc chacun peut vérifier que ce que sert counted.fr correspond au code source.

Mis à jour le 25 octobre 2026

Le lien est la clé

Créer un projet tire une clé aléatoire de 32 octets sur l'appareil. Le lien de partage la transporte, encodée en base64url, après le # :

https://counted.fr/projects/<uuid>#<clé>

Par la norme HTTP, le fragment reste côté client : il ne fait pas partie de la requête, donc il n'apparaît jamais dans les journaux du serveur ni dans un en-tête Referer. À l'ouverture, le client range la clé localement et retire le fragment de la barre d'adresse. C'est tout le modèle d'accès pour les personnes sans compte : qui a le lien peut lire et modifier le projet. Traitez-le comme une clé de maison.

Ce qui est chiffré, et comment

Chaque enregistrement est sérialisé en JSON et chiffré d'un bloc avec XChaCha20-Poly1305, avec un nonce aléatoire de 24 octets neuf à chaque appel. Le tag Poly1305 de 16 octets fait échouer le déchiffrement net en cas de mauvaise clé ou d'octet altéré.

EnregistrementChamps chiffrés
Projetnom, devise, description
Participantnom
Dépensenom, montant, date, type, description, catégorie, devise d'origine et taux
Ligne de paiementmontant, a payé ou doit
Dépense récurrentemodèle, échéancier, curseur
Comptenom affiché, préférences, coordonnées de paiement

Pourquoi pas AES-256-GCM : WebAssembly n'a pas AES-NI, donc ChaCha20 est à la fois plus rapide et à temps constant en logiciel, et le nonce de 24 octets rend les collisions de nonces aléatoires négligeables. La cryptographie tourne en Rust (la crate chacha20poly1305), compilée en WebAssembly pour le web et en natif pour les applications iOS et Android. Soldes, remboursements et statistiques sont aussi calculés sur l'appareil : le serveur n'a jamais besoin d'un montant.

Les comptes facultatifs, et ce que coûte le séquestre des clés

Une clé qui ne vit que sur un appareil disparaît avec le premier téléphone perdu. Pour ceux qui choisissent de créer un compte, chaque clé de projet est donc aussi stockée sur le serveur, enveloppée dans une clé de compte dérivée sur l'appareil avec Argon2id (64 Mio, t=3) à partir du mot de passe et d'un sel propre au compte. Le serveur stocke ces octets et ne peut pas les lire.

C'est un compromis assumé. Sans séquestre, quelqu'un qui détenait la base de données et le mot de passe d'un utilisateur n'obtenait rien de ses projets. Avec le séquestre, il obtient tous les projets de ce compte. L'autre option était de n'offrir aucune récupération, ce qui est pire pour la plupart des gens. Les membres anonymes n'ont pas de séquestre : leurs seules copies sont le lien et leur appareil.

Le mot de passe ne quitte jamais l'appareil

La connexion n'envoie pas le mot de passe. Le client envoie une preuve, un second Argon2id du mot de passe avec un sel de connexion distinct, et le serveur ne garde que SHA-256(preuve), comparé à temps constant. Rien de ce que le serveur reçoit ou stocke ne permet de dériver la clé du compte, et le serveur ne fait aucune dérivation de clé lui-même. Le prix : un aller-retour de plus pour récupérer le sel de connexion.

Cela veut aussi dire qu'un mot de passe oublié ne peut pas être réinitialisé. Personne, nous compris, ne peut déchiffrer les projets du compte sans lui.

Ce que le serveur voit quand même

Se contenter de dire « zero-knowledge » serait malhonnête. Le serveur voit :

  • Pour les comptes : l'e-mail, une empreinte de la preuve de connexion, les sels de dérivation, quel compte est dans quel projet, les liens d'amitié entre comptes, des empreintes des e-mails invités calculées avec un secret du serveur (HMAC-SHA256), les clés publiques et, si les notifications sont activées, le jeton push et sa langue.
  • Pour tout le monde : l'adresse IP, l'agent utilisateur et l'heure dans des journaux gardés 30 jours au plus, la taille et le moment des écritures chiffrées, et des compteurs quotidiens sur des tables entières.
  • La forme de chaque projet, en nombres seulement : combien de participants et de dépenses, quand chaque dépense a été ajoutée, modifiée ou supprimée et, pour un compte qui a choisi qui il est dans un projet, quel participant il a choisi. Depuis la version 3.2.5, qui figure dans une dépense, qui l'a saisie et si le projet est clos sont chiffrés aussi. Un projet enregistré pour la dernière fois par une version antérieure garde ces liens sur le serveur jusqu'à ce qu'un de ses membres l'ouvre avec une application à jour, qui les déplace dans les données chiffrées ; les sauvegardes les conservent au plus 30 jours de plus.
  • Un import Tricount : le navigateur ne peut pas appeler Tricount directement, donc le serveur récupère le compte partagé à sa place et le transmet en clair. Il n'est ni conservé ni journalisé ; l'appareil le chiffre avant de l'enregistrer dans Counted.
  • La longueur des données chiffrées : un chiffrement par flot garde la longueur du texte, donc le serveur peut distinguer une dépense avec description, ou saisie dans une devise étrangère, d'une dépense sans. Jamais le contenu.

Il ne voit jamais les noms, montants, dates, descriptions ni noms de projets. Chaque colonne en clair est listée et justifiée dans les notes de conception, et une vérification avant chaque mise en production échoue si le schéma en gagne une qui ne l'est pas.

Vous pouvez vérifier le code

Le client, tout ce qui voit un jour du texte en clair, est publié sous licence AGPL sur github.com/counted-labs/counted. Le build est reproductible : la CI le reconstruit à partir de zéro, compare le SHA-256 de chaque fichier et signe la liste avec Sigstore. counted.fr/verify montre les empreintes de ce qui est servi et comment les reconstruire vous-même.

Le serveur est fermé, pour protéger les fonctions payantes pour les entreprises prévues de ce côté. Il ne détient jamais que des données chiffrées, donc ce choix ne change rien à la confidentialité d'un projet.

Les limites connues

  • Le chiffrement de bout en bout sur le web fait encore confiance à la page que vous chargez. /verify prouve qu'une version correspond à son code source, et un moniteur public vérifie toutes les six heures, depuis GitHub, que counted.fr sert une version signée et n'exécute aucun autre code. Ni l'un ni l'autre ne prouve que la page que vous venez de charger est cette version : une substitution servie à un seul utilisateur passerait inaperçue. Les applications iOS et Android embarquent leur code à l'installation, donc une seule requête ne peut pas le remplacer.
  • Pas encore d'audit indépendant. Sept audits internes ont été rédigés, avec leurs correctifs.
  • Un lien qui fuit expose le projet. Il n'y a pas de contrôle d'accès par membre ni de rotation de clé, par conception.

Voyez-le sur un vrai projet

Ouvrez la démo avec l'onglet réseau de votre navigateur : chaque écriture est chiffrée.

À lire aussi

Nous éditons Counted. Une erreur dans ce guide ? Écrivez-nous.