**Motivations:** - Implement BIP39 mnemonic import for identity creation - Add password-based key protection for enhanced security - Improve pairing workflow with QR code and URL display - Migrate hash cache from LocalStorage to IndexedDB for better scalability - Update signet-dashboard and mempool components **Root causes:** - N/A (feature implementations) **Correctifs:** - N/A (no bug fixes in this commit) **Evolutions:** - BIP39 mnemonic import: Support for 12/24 word English mnemonics with BIP32 derivation path m/44'/0'/0'/0/0 - Key protection: Password-based encryption of private keys at rest with unlock/lock functionality - Pairing workflow: QR code and URL display for device pairing, form-based word exchange between devices - IndexedDB migration: Hash cache moved from LocalStorage to IndexedDB to avoid size limitations - Global action bar: URL parameter support for navigation - Pairing connection: Enhanced pairing status management **Pages affectées:** - userwallet/src/utils/identity.ts - userwallet/src/utils/keyProtection.ts - userwallet/src/utils/sessionUnlockedKey.ts - userwallet/src/utils/indexedDbStorage.ts - userwallet/src/utils/cache.ts - userwallet/src/utils/pairing.ts - userwallet/src/components/UnlockScreen.tsx - userwallet/src/components/PairingDisplayScreen.tsx - userwallet/src/components/PairingSetupBlock.tsx - userwallet/src/components/GlobalActionBar.tsx - userwallet/src/components/HomeScreen.tsx - userwallet/src/components/ImportIdentityScreen.tsx - userwallet/src/components/DataExportImportScreen.tsx - userwallet/src/hooks/useIdentity.ts - userwallet/src/hooks/usePairingConnected.ts - userwallet/src/services/syncService.ts - userwallet/src/services/pairingConfirm.ts - userwallet/src/App.tsx - userwallet/package.json - userwallet/docs/specs.md - userwallet/docs/storage.md - userwallet/docs/synthese.md - signet-dashboard/public/*.html - signet-dashboard/public/app.js - signet-dashboard/public/styles.css - mempool (submodule updates) - hash_list.txt, hash_list_cache.txt, utxo_list.txt, utxo_list_cache.txt, fees_list.txt - features/*.md (documentation files)
2065 lines
64 KiB
Markdown
2065 lines
64 KiB
Markdown
## Synthèse
|
||
|
||
- **Modèle** : Messages publiés sans signatures ni clés ; signatures et clés publiées séparément ; tout adressé par hash canonique ; récupération par **GET uniquement** (pull).
|
||
- **Objets** : Service, Contrat, Champ, Action, ActionLogin, Membre, Pair, MessageBase, Hash, Signature, Validateurs, MsgChiffre, MsgSignature, MsgCle.
|
||
- **Graphe** : Service → Contrat → Champ → Action(login) → Membre → Pair ; contraintes « au moins 1 parent ».
|
||
- **Pairing** : UUID pair ↔ mots BIP32 ; pairing **obligatoire** pour login.
|
||
- **Écrans** : accueil, création/import identité, relais, pairing, sync, services, chemin login, challenge, signatures mFA, publication, résultat.
|
||
- **Machine à états** : S_INIT → S_HOME, S_SYNC_GLOBAL, S_PAIR_*, S_LOGIN_*, etc., avec erreurs récupérables / fatales.
|
||
|
||
---
|
||
|
||
Lister les étapes et ecran d'un login basé sur ce principe :
|
||
* Génération de cles secp256k1 pour signer et vérifier les signatures
|
||
* login sans serveur central par verification de conformité contrat / signature
|
||
* pairing obligatoire pour se connecter (mFA)
|
||
|
||
Contrat d'identié avec types name: au moins
|
||
|
||
|
||
|
||
Service:
|
||
Contrat
|
||
Type names chiffrés dont service
|
||
|
||
|
||
Contrat :
|
||
Message à valider
|
||
types name chiffrés dont contrat
|
||
|
||
Champ :
|
||
Message à valider
|
||
types name chiffrés dont champ
|
||
+ contrats parents uuid, au mois 1
|
||
|
||
ActionLogin:
|
||
Action
|
||
Types names chiffrés dont login
|
||
|
||
Action:
|
||
Message à valider
|
||
types name chiffrés dont action
|
||
+ Auteurs de l'action
|
||
+ contrats parents uuid, au moins 1
|
||
|
||
Objets créés lors de la création :
|
||
|
||
Lors de la création d'un Pair :
|
||
- Création automatique d'un Pair (MessageBase avec types_names_chiffres incluant "pair")
|
||
- Le Pair doit être associé à au moins un Membre (membres_parents_uuid, au moins 1)
|
||
|
||
Lors de la création d'un Membre :
|
||
- Création automatique d'un Membre (MessageAValider avec types_names_chiffres incluant "membre")
|
||
- Le Membre doit être associé à au moins une Action (actions_parents_uuid, au moins 1)
|
||
|
||
Lors de la création d'un contrat de login d'un Service :
|
||
- Création automatique d'un Contrat (MessageAValider avec types_names_chiffres incluant "contrat")
|
||
- Création automatique d'une ActionLogin (Action avec types_names_chiffres incluant "login")
|
||
- Création automatique d'un Membre (MessageAValider avec types_names_chiffres incluant "membre")
|
||
- L'ActionLogin est associée au Contrat (contrats_parents_uuid incluant l'UUID du Contrat)
|
||
- Le Membre est associé à l'ActionLogin (actions_parents_uuid incluant l'UUID de l'ActionLogin)
|
||
- Le nom du contrat de login est passé en paramètre initial à l'iframe ou au site, par défaut "default"
|
||
|
||
Membre :
|
||
Message à valider
|
||
types name chiffrés dont membre
|
||
Actions parents uuid, au moins 1
|
||
|
||
Pair :
|
||
MessageBase
|
||
Types names chiffrés dont pair
|
||
Membres parents uuid, au moins 1
|
||
|
||
Message Base:
|
||
Hash du JSON sans le hash, sans la signature
|
||
uuid
|
||
Version
|
||
Types names chiffrés dont pair
|
||
Clés de chiffrement avec tous les paramètres et l'algo
|
||
Datajson dont les attributs :
|
||
- Obligatoires : services uuid, types uuid
|
||
- optionnels :label, description longue, description courte, photo, image, bannière, URL, paragraphes (couples de textes + images), tarif
|
||
Timestpamp
|
||
Liste de relais (IP)
|
||
Hash du JSON signé du pair avec dans la signature le hash, la clé publique et la signature
|
||
Version logicielle
|
||
|
||
Hash :
|
||
* Hash du JSON (sans le hash, sans les signatures, sans clés de chiffrement)
|
||
* Algo
|
||
|
||
Signature :
|
||
* hash
|
||
* clé publique
|
||
* signature cryptographique
|
||
* Nonce et autre matériel éventuel
|
||
|
||
Message à valider :
|
||
* MessageBase +
|
||
* Validateurs du message
|
||
|
||
Validateurs:
|
||
Listes des membres du role, au moins 1
|
||
* Pour chacun des membres : la liste des signatures obligatoires des autres membres et/ou de lui même
|
||
|
||
Message individuel de déchiffrement :
|
||
* hash du message
|
||
* clé de chiffrement du message chiffré: + clé de chiffrement chiffrée avec tous le paramètres et algo
|
||
* df : + diffie-hellman à scanner contenant une clé de déchiffrement de la clé de déchiffrement dans le secret partagé
|
||
|
||
Message de signature :
|
||
* Signature
|
||
|
||
Les messages sont postés sans les signatures et sans les clés de chiffrement, les signatures et les cles sont postées spécifiquement après. Les messages sont tous envoyés chiffrés de type:
|
||
* hash
|
||
* Message chiffré
|
||
* datajson public
|
||
|
||
LEs signatures et les clés de chiffrement ne sont pas récupérées au get elles sont récupérées spécifiquement apres et ajoutés aux messages stockés
|
||
|
||
Tous les envois passent par des relais qui stockent et relaient entre relais (sauvegarde des hash pour ne pas relayer ceux déjà reçus)
|
||
Périodiquement et par services les client font des cet pour récupérer les informations
|
||
|
||
Chacun publie pour tous sans destinataire indiqué mais chiffré. Mais un diffie hellman est possible avec tous les pairs concernés pour d'échanger par la suite des clés de déchiffrement entre clé publiques, ce matériel exploitable que par les parties concernées est envoyé lors des échanges de clés
|
||
|
||
Pour ajouter un uuid d'un pair à un un membre celui ci est converti via bip32 en une liste de mots puis reconstitué (device 2 affiche les mots, device les saisis), ainsi l'uuid est une clé qui ne sert que d'identifiant
|
||
|
||
Pour se logguer il faut founir des signatures des pairs attendues dans l'action de type login de ce membre ayant dans ses services parents uuid l'uuid du service sur lequel il veut se connecter
|
||
|
||
Pour savoir si il y a un message à récupérer et déchiffrer il faut récupérer et scanner tous (depuis la date anniversaire de création des clés)les messages de clés depuis (proposer un bloom filtrer et/ou des arbres de merkle pur gérer l'historique des hash et ne pas tout rescanner) aucun message n'est reçu ils sont tous récupérés (get) en fonction des deffie hellman
|
||
|
||
|
||
Introduction
|
||
Ce qui suit décrit, de manière opérationnelle, les étapes et les écrans d’un login fondé sur des clés secp256k1, une validation “sans serveur central” (conformité des contrats et signatures), et un pairing obligatoire jouant le rôle de second facteur. La description suppose un réseau de relais stockant et relayant des objets immuables adressés par hash, avec séparation stricte entre messages, signatures et clés de chiffrement, récupérées par appels dédiés.
|
||
|
||
Principes structurants à respecter à chaque étape
|
||
Séparation des flux et des objets
|
||
|
||
* Un message “métier” est publié sans signatures et sans clés de chiffrement.
|
||
* Les signatures sont publiées ensuite, séparément, via des objets “Message de signature”.
|
||
* Les clés (ou matériels) de déchiffrement sont publiées ensuite, séparément, via des objets “Message individuel de déchiffrement”.
|
||
* Les requêtes de récupération ne renvoient pas automatiquement signatures et clés ; elles sont récupérées explicitement et rattachées localement au message stocké.
|
||
|
||
Adressage et immutabilité
|
||
|
||
* Tout objet est adressé par hash (hash du JSON canonique “sans hash, sans signatures, sans clés de chiffrement” selon la règle donnée).
|
||
* Un relais conserve l’historique des hash reçus pour ne pas relayer deux fois.
|
||
|
||
Confidentialité “publish to all”
|
||
|
||
* Tout est publié sans destinataire explicite.
|
||
* Le contenu utile est chiffré ; seuls les pairs capables d’obtenir (ou de dériver) la clé de déchiffrement peuvent lire.
|
||
* Les échanges de matériels de déchiffrement peuvent s’appuyer sur Diffie-Hellman (ECDH secp256k1) entre clés publiques concernées ; le “matériel DH” est publiable car inexploitable par les tiers.
|
||
|
||
Conformité “contrat / signature”
|
||
|
||
* La “vérité” d’un login provient de la vérification locale d’un graphe de contrats (service → contrat → champ → action → membre → pair) et de la satisfaction des validateurs (signatures requises, rôles, multi-signatures).
|
||
|
||
Pairing obligatoire (mFA)
|
||
|
||
* Sans association préalable d’au moins un “pair” (device/instance), aucune session n’est autorisée.
|
||
* L’ajout de l’UUID d’un pair à un membre se fait par conversion BIP32 en mots affichés/saisis pour limiter les erreurs et éviter l’échange brut d’identifiants.
|
||
|
||
Objets et contraintes à refléter dans l’UX (rappel synthétique)
|
||
Les écrans doivent permettre de construire, vérifier et exploiter ces objets et liens (UUID “parents” au moins 1 partout où requis).
|
||
|
||
Service
|
||
|
||
* Contrat
|
||
* Types names chiffrés dont “service”
|
||
|
||
Contrat
|
||
|
||
* Message à valider
|
||
* Types names chiffrés dont “contrat”
|
||
|
||
Champ
|
||
|
||
* Message à valider
|
||
* Types names chiffrés dont “champ”
|
||
* Contrats parents UUID, au moins 1
|
||
|
||
ActionLogin
|
||
|
||
* Action
|
||
* Types names chiffrés dont “login”
|
||
|
||
Action
|
||
|
||
* Message à valider
|
||
* Types names chiffrés dont “action”
|
||
* Validateurs de l’action
|
||
* Contrats parents UUID, au moins 1
|
||
|
||
Membre
|
||
|
||
* Message à valider
|
||
* Types names chiffrés dont “membre”
|
||
* Actions parents UUID, au moins 1
|
||
|
||
Pair
|
||
|
||
* MessageBase
|
||
* Types names chiffrés dont “pair”
|
||
* Membres parents UUID, au moins 1
|
||
|
||
MessageBase
|
||
|
||
* Hash du JSON sans le hash, sans la signature
|
||
* UUID
|
||
* Version
|
||
* Types names chiffrés dont “pair” (et plus généralement le type de l’objet)
|
||
* Clés de chiffrement avec paramètres et algo
|
||
* Datajson
|
||
|
||
* obligatoires : services UUID, types UUID
|
||
* optionnels : label, descriptions, médias, URL, paragraphes, tarif
|
||
* Timestamp
|
||
* Liste de relais (IP)
|
||
* Hash du JSON signé du pair, avec dans la signature : hash + clé publique + signature
|
||
* Version logicielle
|
||
|
||
Hash
|
||
|
||
* Hash du JSON (sans hash, sans signatures, sans clés de chiffrement)
|
||
* Algo
|
||
|
||
Signature
|
||
|
||
* Hash
|
||
* Clé publique
|
||
* Signature cryptographique
|
||
* Nonce et matériel éventuel
|
||
|
||
Message à valider
|
||
|
||
* MessageBase
|
||
* Validateurs du message
|
||
|
||
Validateurs
|
||
|
||
* Liste des membres du rôle, au moins 1
|
||
* Pour chacun : liste des signatures obligatoires (lui-même et/ou autres membres)
|
||
|
||
Message individuel de déchiffrement
|
||
|
||
* Hash du message
|
||
* Clé de chiffrement du message chiffré, incluant une clé de chiffrement chiffrée avec paramètres et algo
|
||
* Matériel DH à scanner contenant une clé de déchiffrement (dans le secret partagé)
|
||
|
||
Message de signature
|
||
|
||
* Signature
|
||
|
||
Écrans et parcours, de bout en bout
|
||
Écran d’accueil
|
||
Objectif
|
||
|
||
* Démarrer une session locale, présenter l’état du wallet d’identité (clés, pairs, cache), proposer connexion ou onboarding.
|
||
|
||
Éléments affichés
|
||
|
||
* Statut “identité locale présente / absente”
|
||
* Empreinte courte de la clé publique principale (secp256k1), si existante
|
||
* Statut “pairing requis : non satisfait / satisfait”
|
||
* Statut réseau relais : atteignables, latence, dernier sync, file d’objets en attente
|
||
* Boutons : Créer identité, Importer identité, Se connecter, Gérer pairs, Paramètres relais, Synchroniser maintenant
|
||
|
||
Écran de création d’identité locale
|
||
Objectif
|
||
|
||
* Générer la paire de clés secp256k1 (signature) et initialiser les paramètres de chiffrement.
|
||
|
||
Actions
|
||
|
||
* Génération clé privée secp256k1
|
||
* Dérivation clé publique secp256k1
|
||
* Éventuelle dérivation de sous-clés (BIP32) si vous utilisez un arbre pour identités/pairs/services
|
||
|
||
Champs et options
|
||
|
||
* Nom local de l’identité (purement local)
|
||
* Option de protection locale (PIN, biométrie, mot de passe) pour chiffrer la clé privée au repos
|
||
* Paramètres crypto par défaut (algorithmes symétriques, KDF, formats) pour “Clés de chiffrement avec tous les paramètres”
|
||
|
||
Sorties
|
||
|
||
* Identité locale créée
|
||
* Date “anniversaire de création des clés” enregistrée (sert de point de départ de scan)
|
||
* Cache local initialisé (index des hash vus, index services/types, index ECDH)
|
||
|
||
Écran d’import d’identité
|
||
Objectif
|
||
|
||
* Restaurer la clé privée (ou seed BIP32) et les métadonnées locales nécessaires.
|
||
|
||
Actions
|
||
|
||
* Import seed / clé privée
|
||
* Recalcul clé publique
|
||
* Réindex local minimal
|
||
|
||
Contrôles
|
||
|
||
* Vérifier cohérence clé publique dérivée
|
||
* Vérifier format/versions
|
||
|
||
Écran de gestion des relais
|
||
Objectif
|
||
|
||
* Déclarer la liste de relais, tester, prioriser, et configurer la stratégie de synchronisation.
|
||
|
||
Champs
|
||
|
||
* Liste de relais (IP ou endpoints)
|
||
* Stratégie : périodicité, par services, par fenêtres temporelles
|
||
* Paramètres anti-resscan : Bloom filter, Merkle trees (optionnel), taille de cache de hash
|
||
|
||
Actions
|
||
|
||
* Test connectivité
|
||
* Mise à jour de la liste et sauvegarde locale
|
||
|
||
Écran de pairing (obligatoire avant login)
|
||
Objectif
|
||
|
||
* Associer au moins un pair à un membre, via procédure robuste “mots BIP32”, pour fournir le second facteur.
|
||
|
||
Pré-requis conceptuel
|
||
|
||
* Un pair est un objet rattaché à un ou plusieurs membres (Membres parents UUID ≥ 1).
|
||
* L’association se matérialise par la publication d’objets (selon votre modèle) où l’UUID du pair est présent dans le graphe du membre, et validé par les signatures attendues.
|
||
|
||
Sous-écran “ajouter un pair”
|
||
Deux modes pratiques
|
||
|
||
* Mode “ce device devient un pair”
|
||
|
||
* Générer/attribuer un UUID pair local
|
||
* Afficher la séquence de mots BIP32 dérivée de cet UUID
|
||
* Mode “associer un pair existant”
|
||
|
||
* Saisir les mots BIP32 affichés par l’autre device
|
||
* Reconstituer l’UUID pair
|
||
* Préparer la publication des messages nécessaires pour lier ce pair au membre
|
||
|
||
Contrôles
|
||
|
||
* Vérification de saisie (checksum/wordlist)
|
||
* Vérification que le pair n’est pas déjà associé
|
||
* Vérification que le membre cible est connu (ou possibilité de le découvrir via sync)
|
||
|
||
Sorties
|
||
|
||
* UUID pair reconnu et enregistré localement
|
||
* Publication (ou préparation) des messages “pair” / “membre” nécessaires à l’association
|
||
* Mise en file des signatures et clés de chiffrement à publier séparément
|
||
|
||
Écran de synchronisation initiale (découverte)
|
||
Objectif
|
||
|
||
* Récupérer et indexer l’ensemble des messages utiles pour construire le graphe et détecter ce qui est déchiffrable.
|
||
|
||
Contraintes imposées par votre modèle “publish to all”
|
||
|
||
* Aucun message n’est “reçu” : tout est “récupéré (get)” puis filtré localement.
|
||
* Pour détecter un message déchiffrable, il faut scanner les messages de clés depuis la date anniversaire de création des clés (ou depuis le dernier checkpoint).
|
||
|
||
Éléments affichés
|
||
|
||
* Fenêtre temporelle de scan (début = date anniversaire / dernier checkpoint, fin = maintenant)
|
||
* Compteurs : messages récupérés, hash nouveaux, hash déjà vus, signatures en attente de fetch, clés en attente de fetch
|
||
* Indicateur Bloom/Merkle : actif/inactif, taux de faux positifs (si Bloom), profondeur/segments (si Merkle)
|
||
* Liste des services découverts (via datajson.services UUID) et types UUID
|
||
|
||
Actions
|
||
|
||
* Synchroniser maintenant
|
||
* Affiner par service
|
||
* Construire/mettre à jour l’index Merkle ou Bloom côté client
|
||
* Exporter un checkpoint local (hash racine Merkle, ou bitset Bloom) si utile
|
||
|
||
Étapes techniques de sync côté client
|
||
|
||
* GET messages chiffrés “hash + message chiffré + datajson public” depuis relais, filtrés par période et/ou service
|
||
* Déduplication par hash (cache local + cache relais)
|
||
* Pour chaque message potentiel : tenter d’identifier la nécessité d’une clé (via type UUID, service UUID, et index ECDH)
|
||
* Fetch dédié des “Message individuel de déchiffrement” pertinents (par hash) et construction du matériel ECDH
|
||
* Déchiffrement, parsing JSON, calcul hash canonique, vérification cohérence “Hash du JSON sans hash…”
|
||
* Fetch dédié des “Message de signature” (par hash) et attachement local
|
||
* Vérification des signatures secp256k1 conformément aux validateurs du message
|
||
|
||
Écran de sélection du service
|
||
Objectif
|
||
|
||
* Choisir le service (service UUID) sur lequel l’utilisateur veut s’authentifier.
|
||
|
||
Affichage
|
||
|
||
* Liste des services disponibles (découverts localement)
|
||
* Pour chaque service : statut de confiance
|
||
|
||
* “Contrat complet et valide”
|
||
* “Contrat incomplet (éléments manquants)”
|
||
* “Contrat invalide (hash/signature/validateurs non satisfaits)”
|
||
* Option de rafraîchissement sync “par service”
|
||
|
||
Action
|
||
|
||
* Choisir un service → déclenche construction du chemin de validation login
|
||
|
||
Écran “construction du chemin login”
|
||
Objectif
|
||
|
||
* Construire et afficher la chaîne d’objets nécessaires, puis calculer la liste exacte des signatures attendues.
|
||
|
||
Chaîne minimale attendue
|
||
|
||
* Service (service UUID)
|
||
* Contrat(s) rattachés
|
||
* Champs (au moins 1 champ avec contrats parents UUID)
|
||
* ActionLogin → Action de type login
|
||
* Membre (ayant actions parents UUID incluant l’action login)
|
||
* Pair(s) (ayant membres parents UUID incluant ce membre)
|
||
|
||
Travail du client
|
||
|
||
* Résoudre les liens par UUID parents, vérifier “au moins 1” partout où requis
|
||
* Vérifier les “types names chiffrés” : existence, déchiffrement si nécessaire, cohérence avec type UUID
|
||
* Pour chaque objet : recalcul hash canonique et comparer au hash déclaré
|
||
* Construire l’ensemble “validateurs” applicables à l’action login et au message de login
|
||
* Produire la matrice “signatures obligatoires” : qui doit signer quoi, et sous quelles clés publiques
|
||
|
||
Affichage conseillé
|
||
|
||
* Graphe ou liste hiérarchique (service → … → pair), avec statut vert/rouge par nœud
|
||
* Détail des signatures requises : membre(s) valideur(s), nombre minimal, dépendances “autres membres et/ou lui-même”
|
||
|
||
Écran “vérification du pairing requis”
|
||
Objectif
|
||
|
||
* S’assurer que les pairs exigés par l’action login sont présents et activables localement.
|
||
|
||
Vérifications
|
||
|
||
* Les UUID de pairs attendus sont connus localement (ou récupérables)
|
||
* Chaque pair attendu peut produire une signature (donc la clé privée correspondante est accessible localement ou via device associé)
|
||
* Le mapping pair ↔ membre ↔ action login est valide et signé selon validateurs
|
||
|
||
Cas usuels
|
||
|
||
* Pair local unique : ce device signe
|
||
* Multi-pair : exiger au moins N signatures de pairs distincts (mFA renforcé)
|
||
* Pair distant : déclencher un flux “signer sur l’autre device” via procédure de partage (QR, mots, lien) sans serveur central, uniquement par publication de signatures
|
||
|
||
Écran “challenge / message à valider”
|
||
Objectif
|
||
|
||
* Générer le “Message à valider” de la session de login, puis organiser sa signature et sa vérification.
|
||
|
||
Contenu minimal à préparer
|
||
|
||
* MessageBase complet (uuid, version, timestamp, types UUID, services UUID, relais, version logicielle, datajson public minimal)
|
||
* Hash canonique calculé selon règle
|
||
* Nonce de session et/ou matériel anti-rejeu dans “Signature” (nonce et autre matériel éventuel)
|
||
* Références explicites au service UUID cible
|
||
* Références explicites à l’action login UUID et au membre UUID (selon votre modèle), pour lier la preuve à l’intention
|
||
|
||
Affichage
|
||
|
||
* Résumé des attributs publics (service UUID, type UUID, timestamp, relais)
|
||
* Statut “détecté comme conforme au contrat : oui/non”
|
||
* Bouton “Signer” (désactivé si pairing non satisfait)
|
||
|
||
Écran “signature(s) mFA”
|
||
Objectif
|
||
|
||
* Collecter les signatures requises, potentiellement depuis plusieurs pairs/devices.
|
||
|
||
Flux de signature
|
||
|
||
* Pour le pair local
|
||
|
||
* Signer hash canonique secp256k1
|
||
* Produire objet “Message de signature” : hash + clé publique + signature + nonce/matériel
|
||
* Pour les pairs distants
|
||
|
||
* Afficher un “paquet de demande de signature” (hash, contexte, paramètres)
|
||
* Sur l’autre device : vérifier contexte, signer, publier la signature
|
||
* Sur ce device : récupérer la signature via fetch dédié et l’attacher localement
|
||
|
||
Affichage
|
||
|
||
* Liste des signatures attendues avec état
|
||
|
||
* “manquante”
|
||
* “reçue”
|
||
* “valide”
|
||
* “invalide” (mauvais hash, mauvaise clé publique, signature invalide)
|
||
* Règles de validateurs satisfaites / non satisfaites, en temps réel
|
||
|
||
Écran “publication du login”
|
||
Objectif
|
||
|
||
* Publier la preuve de login dans le réseau de relais, conformément à la règle “message d’abord, signatures ensuite, clés ensuite”.
|
||
|
||
Étapes d’émission côté client
|
||
|
||
* Publier le message chiffré (objet contenant : hash + message chiffré + datajson public)
|
||
|
||
* Sans signatures
|
||
* Sans clés de chiffrement
|
||
* Publier ensuite, séparément, les “Message de signature” nécessaires
|
||
* Publier ensuite, séparément, les “Message individuel de déchiffrement” nécessaires (si d’autres parties doivent déchiffrer, par exemple le service ou un ensemble de validateurs)
|
||
* Relais : propagation inter-relais, déduplication par hash
|
||
|
||
Affichage
|
||
|
||
* Liste des relais cibles, état de publication par relais
|
||
* Hash final de la preuve
|
||
* Statut “propagation suffisante” (par exemple M relais sur N ont confirmé stockage)
|
||
|
||
Écran “vérification côté service sans serveur central”
|
||
Objectif
|
||
|
||
* Décrire ce que fait le “service” (ou l’application de service) pour accepter la session, en ne reposant que sur contrats + signatures.
|
||
|
||
Mécanique de vérification (côté service)
|
||
|
||
* Récupérer le message publié (par hash ou par scan périodique “par service”)
|
||
* Récupérer explicitement signatures associées
|
||
* Récupérer explicitement matériels de déchiffrement si nécessaire
|
||
* Déchiffrer, recalculer hash canonique, comparer
|
||
* Vérifier signatures secp256k1, clés publiques, nonces
|
||
* Rejouer la construction du graphe (service → … → action login → membre → pairs) depuis les UUID et messages disponibles
|
||
* Vérifier validateurs : liste des membres du rôle, signatures obligatoires, seuils
|
||
* Vérifier anti-rejeu : timestamp, nonce, fenêtre temporelle, unicité du hash/nonce
|
||
* Si OK : émettre un “jeton local” (non central) ou ouvrir une session locale ; sinon refuser
|
||
|
||
Écran “résultat de connexion”
|
||
Objectif
|
||
|
||
* Donner un état explicite, traçable, et diagnostiquable.
|
||
|
||
États possibles
|
||
|
||
* Connecté : preuve acceptée
|
||
* Refusé : contrat incomplet
|
||
* Refusé : signatures insuffisantes
|
||
* Refusé : signature invalide
|
||
* Refusé : anti-rejeu déclenché (nonce déjà vu / timestamp hors fenêtre)
|
||
* Refusé : pairing requis non satisfait
|
||
* Refusé : impossibilité de récupérer signatures/clés après délai
|
||
|
||
Affichage recommandé
|
||
|
||
* Hash de la preuve
|
||
* Service UUID
|
||
* Liste des validateurs satisfaits / non satisfaits
|
||
* Journal succinct : quels objets manquaient (hash), quelles signatures manquaient (clé publique), quels matériels DH manquaient
|
||
|
||
Écran “récupération et déchiffrement en continu”
|
||
Objectif
|
||
|
||
* Assurer le fonctionnement périodique “par services” : scan, fetch des clés, fetch des signatures, mise à jour du graphe et des droits.
|
||
|
||
Fonctions
|
||
|
||
* Planification périodique : pour chaque service connu, GET des nouveaux messages depuis dernier checkpoint
|
||
* Dédup hash
|
||
* Tentative de correspondance via index ECDH pour identifier les messages potentiellement déchiffrables
|
||
* Fetch des messages de clés (déchiffrement), puis fetch des signatures, puis validation
|
||
|
||
Optimisations à exposer (au moins comme options avancées)
|
||
|
||
* Bloom filter
|
||
|
||
* Objectif : éviter de rescanner tout l’historique des hash
|
||
* Données : bitset local, éventuellement partagé entre devices
|
||
* Limite : faux positifs possibles → nécessite vérification finale par hash
|
||
* Arbres de Merkle
|
||
|
||
* Objectif : prouver rapidement la présence/absence d’un hash dans un ensemble et synchroniser des segments
|
||
* Données : racines par période/service, preuve d’inclusion
|
||
* Limite : complexité de maintenance côté relais et côté client
|
||
|
||
Détails critiques de validation à intégrer (pour éviter des ambiguïtés en production)
|
||
Canonisation JSON
|
||
|
||
* Définir une canonisation stricte : ordre des clés, encodage, normalisation des nombres/chaînes, gestion des tableaux.
|
||
* Sans cela, “Hash du JSON” devient instable entre implémentations.
|
||
|
||
Gestion des versions
|
||
|
||
* “Version” et “Version logicielle” doivent être prises en compte dans la validation (compatibilité ascendante, migrations).
|
||
* Le client doit afficher clairement la version d’un contrat et refuser ou isoler les versions non supportées.
|
||
|
||
Anti-rejeu
|
||
|
||
* Timestamp seul est insuffisant ; exiger un nonce unique par tentative, et un cache de nonces vus (par service) sur une fenêtre glissante.
|
||
* Le service doit rejeter un hash/nonce déjà accepté.
|
||
|
||
Clés publiques et identité
|
||
|
||
* La clé publique incluse dans la signature doit être reliée, par le graphe et les validateurs, au pair attendu.
|
||
* Interdire l’acceptation d’une signature “valide cryptographiquement” mais non autorisée “contractuellement”.
|
||
|
||
Séparation signatures / clés
|
||
|
||
* Prévoir un état “message reçu mais indéchiffrable (clé manquante)” et “message déchiffré mais non validé (signature manquante)”.
|
||
* L’UX doit rendre ces états visibles, sinon les utilisateurs concluent à des pertes de données.
|
||
|
||
Conclusion
|
||
Un login conforme à ce modèle n’est pas un simple écran “identifiant/mot de passe”, mais un enchaînement de construction et de vérification d’un graphe contractuel, suivi d’une collecte de signatures multi-pairs, puis d’une publication en trois temps (message, signatures, clés), le tout synchronisé via des relais. La robustesse globale vient de la cohérence entre canonisation des hash, règles de validateurs, anti-rejeu, et de la capacité du client à scanner efficacement l’historique (Bloom/Merkle) sans jamais supposer qu’un message “arrive” par push.
|
||
|
||
Si une suite est souhaitée, la prochaine étape naturelle consiste à produire une spécification d’écrans sous forme de maquettes textuelles (composants, états, erreurs, journaux), puis une machine à états formelle du protocole de login (états, transitions, timeouts, reprise sur erreur), strictement alignée sur les objets et contraintes listés ci-dessus.
|
||
|
||
# Écrans à produire pour login sans serveur central (secp256k1 + contrats + pairing mFA)
|
||
|
||
## Principes UX et contraintes non négociables
|
||
|
||
Les règles suivantes doivent être visibles dans la conception des écrans (au minimum en “états avancés”, logs, diagnostics) :
|
||
|
||
- Tous les messages sont récupérés par GET (aucun push).
|
||
- Les messages “métier” sont publiés sans signatures et sans clés de chiffrement.
|
||
- Les signatures sont publiées après, séparément.
|
||
- Les clés/matériels de déchiffrement sont publiés après, séparément.
|
||
- Un GET de message ne renvoie pas signatures et clés : elles sont fetch spécifiquement ensuite.
|
||
- Tous les objets sont adressés par hash du JSON canonique (sans hash, sans signatures, sans clés de chiffrement).
|
||
- Le login est une preuve validée localement par graphe (service → contrat → champ → action/login → membre → pair) + validateurs.
|
||
- Le pairing est obligatoire pour autoriser une connexion : au moins un pair associé et attendu par l’action de login.
|
||
- Publication “pour tous” : aucun destinataire explicite. Le message est chiffré et n’est lisible que par les parties capables d’obtenir les clés.
|
||
|
||
## Glossaire des objets manipulés dans l’UI
|
||
|
||
- Service : objet décrivant un service et son contrat associé.
|
||
- Contrat : objet “contrat d’identité”.
|
||
- Champ : objet rattaché à au moins un contrat parent.
|
||
- Action : objet rattaché à au moins un contrat parent, contient des validateurs.
|
||
- ActionLogin : action de type “login”.
|
||
- Membre : objet rattaché à au moins une action parent.
|
||
- Pair : objet rattaché à au moins un membre parent (device/instance).
|
||
- MessageBase : trame commune incluant uuid/version/types/services/timestamp/relais/hash/signature/pubkey.
|
||
- Message à valider : MessageBase + validateurs.
|
||
- Hash : hash du JSON canonique (sans hash, sans signatures, sans clés de chiffrement) + algo.
|
||
- Signature : hash + clé publique + signature + nonce/matériel.
|
||
- Message de signature : objet portant une Signature.
|
||
- Message individuel de déchiffrement : objet portant matériel de déchiffrement + ECDH.
|
||
|
||
## Écran “accueil”
|
||
|
||
### Objectif
|
||
Point d’entrée de l’application : état de l’identité locale, état du pairing, accès au login et à la synchronisation.
|
||
|
||
### Pré-requis
|
||
Aucun.
|
||
|
||
### Composants UI
|
||
- Statut identité locale : présente / absente
|
||
- Empreinte de la clé publique principale (format court)
|
||
- Statut pairing : requis / satisfait / incomplet
|
||
- Statut réseau relais : OK / dégradé / indisponible
|
||
- Dernière synchronisation : date/heure
|
||
- Boutons :
|
||
- Créer une identité locale
|
||
- Importer une identité
|
||
- Se connecter
|
||
- Gérer les pairs
|
||
- Réglages relais
|
||
- Synchroniser maintenant
|
||
|
||
### États / erreurs
|
||
- Identité absente → bouton “Se connecter” désactivé
|
||
- Pairing non satisfait → “Se connecter” possible mais renverra vers pairing obligatoire
|
||
- Relais indisponibles → mode offline (lecture cache uniquement)
|
||
|
||
## Écran “création d’identité locale”
|
||
|
||
### Objectif
|
||
Générer les clés secp256k1 et initialiser les paramètres crypto locaux.
|
||
|
||
### Pré-requis
|
||
Aucun.
|
||
|
||
### Composants UI
|
||
- Nom local de l’identité (optionnel)
|
||
- Protection locale :
|
||
- PIN / mot de passe / biométrie (selon plateforme)
|
||
- Paramètres crypto avancés (optionnel) :
|
||
- Algos de chiffrement symétrique
|
||
- KDF
|
||
- Format canonique JSON
|
||
- Hash (algo)
|
||
|
||
### Actions utilisateur
|
||
- Générer l’identité
|
||
|
||
### Traitements locaux
|
||
- Génération clé privée secp256k1
|
||
- Calcul clé publique secp256k1
|
||
- Enregistrement “date anniversaire de création des clés”
|
||
- Création du cache local :
|
||
- index hash vus
|
||
- index services/types
|
||
- index ECDH (si applicable)
|
||
|
||
### États / erreurs
|
||
- Erreur entropie / RNG indisponible
|
||
- Protection locale non conforme (PIN trop court, etc.)
|
||
|
||
## Écran “import d’identité”
|
||
|
||
### Objectif
|
||
Restaurer une identité existante (clé privée ou seed/hiérarchie).
|
||
|
||
### Pré-requis
|
||
Disposer d’un secret d’import.
|
||
|
||
### Composants UI
|
||
- Mode import :
|
||
- Seed / phrase / clé privée
|
||
- Fichier chiffré (optionnel)
|
||
- Champ d’entrée + validation checksum
|
||
- Protection locale au repos (comme création)
|
||
|
||
### Traitements locaux
|
||
- Recalcul clé publique
|
||
- Vérification cohérence
|
||
- Initialisation cache
|
||
|
||
### États / erreurs
|
||
- Seed invalide
|
||
- Clé privée hors format
|
||
- Incompatibilité de version
|
||
|
||
## Écran “réglages relais”
|
||
|
||
### Objectif
|
||
Configurer la liste de relais et les stratégies de synchronisation.
|
||
|
||
### Composants UI
|
||
- Liste des relais (IP / endpoint)
|
||
- Priorité / ordre (drag & drop)
|
||
- Options :
|
||
- Sync périodique par service
|
||
- Fenêtre de scan par défaut
|
||
- Déduplication locale (taille cache hash)
|
||
- Accélérateurs : Bloom filter / Merkle (avancé)
|
||
- Boutons :
|
||
- Tester relais
|
||
- Ajouter / supprimer relais
|
||
- Sauvegarder
|
||
|
||
### États / erreurs
|
||
- Relais non joignable
|
||
- Timeout réseau
|
||
- Configuration invalide (liste vide)
|
||
|
||
## Écran “synchronisation globale”
|
||
|
||
### Objectif
|
||
Récupérer des messages publiés sur relais, sans destinataire, et mettre à jour le cache local.
|
||
|
||
### Pré-requis
|
||
Identité locale présente.
|
||
|
||
### Composants UI
|
||
- Fenêtre de scan :
|
||
- Début : anniversaire clés / dernier checkpoint
|
||
- Fin : maintenant
|
||
- Sélecteurs :
|
||
- Tous services
|
||
- Service spécifique (si déjà connu)
|
||
- Compteurs :
|
||
- messages récupérés
|
||
- hash nouveaux
|
||
- hash déjà vus
|
||
- messages déchiffrables détectés
|
||
- signatures à récupérer
|
||
- clés à récupérer
|
||
- Boutons :
|
||
- Synchroniser maintenant
|
||
- Pause / reprendre
|
||
- Forcer “fetch signatures”
|
||
- Forcer “fetch clés”
|
||
- Diagnostiquer un hash
|
||
|
||
### Traitements locaux
|
||
- GET messages chiffrés : (hash + message chiffré + datajson public)
|
||
- Déduplication par hash
|
||
- Indexation par service UUID / type UUID
|
||
- Tentatives d’identification :
|
||
- ce message est-il potentiellement déchiffrable ?
|
||
- Fetch dédié des messages “clés” pertinents
|
||
- Déchiffrement, parsing JSON, recalcul hash canonique
|
||
- Fetch dédié des “messages de signature”
|
||
- Vérification signatures secp256k1
|
||
- Mise à jour du graphe (service/contrat/action/membre/pair)
|
||
|
||
### États / erreurs
|
||
- Message présent mais clé manquante → “indéchiffrable”
|
||
- Message déchiffré mais signatures manquantes → “non validé”
|
||
- Hash incohérent (JSON canonique différent) → “objet corrompu / non conforme”
|
||
- Signatures invalides → “preuve invalide”
|
||
|
||
## Écran “gestion des services”
|
||
|
||
### Objectif
|
||
Lister les services connus localement et leur état de validité contractuelle.
|
||
|
||
### Pré-requis
|
||
Au moins une synchronisation effectuée.
|
||
|
||
### Composants UI
|
||
- Liste des services (service UUID)
|
||
- Pour chaque service :
|
||
- label (si disponible et déchiffré)
|
||
- statut contrat :
|
||
- complet et valide
|
||
- incomplet (objets manquants)
|
||
- invalide (signatures/validateurs)
|
||
- dernier sync service
|
||
- Actions :
|
||
- Ouvrir
|
||
- Resync par service
|
||
- Voir graphe
|
||
|
||
### États / erreurs
|
||
- Service détecté mais contrat non résolu → “incomplet”
|
||
- Types names chiffrés non déchiffrables → “affichage minimal”
|
||
|
||
## Écran “détail service / graphe contractuel”
|
||
|
||
### Objectif
|
||
Afficher la chaîne complète : service → contrat → champ → action → membre → pair(s), avec états.
|
||
|
||
### Composants UI
|
||
- Vue hiérarchique ou graphe
|
||
- Nœuds avec :
|
||
- UUID
|
||
- type UUID
|
||
- statut (valide/incomplet/invalide)
|
||
- hash
|
||
- Liste “objets manquants” (hash attendus)
|
||
- Bouton “diagnostic”
|
||
|
||
### Traitements locaux
|
||
- Résolution des parents UUID
|
||
- Validation “au moins 1 parent” sur objets concernés
|
||
- Vérification hash canonique
|
||
- Vérification signatures et validateurs
|
||
|
||
### États / erreurs
|
||
- Cycle détecté dans les UUID parents (si possible) → bloquer
|
||
- Parent absent → incomplet
|
||
|
||
## Écran “gestion des pairs”
|
||
|
||
### Objectif
|
||
Lister les pairs connus et gérer l’association à des membres.
|
||
|
||
### Composants UI
|
||
- Liste des pairs (UUID pair)
|
||
- Pour chaque pair :
|
||
- membres parents UUID
|
||
- statut : associé / en attente / invalide
|
||
- capacité signature : OK / indisponible
|
||
- Actions :
|
||
- Ajouter un pair
|
||
- Associer à un membre
|
||
- Retirer (local uniquement, selon politique)
|
||
- Diagnostiquer
|
||
|
||
## Écran “ajout de pair (mFA)”
|
||
|
||
### Objectif
|
||
Réaliser le pairing obligatoire via conversion BIP32 en mots.
|
||
|
||
### Pré-requis
|
||
Identité locale présente.
|
||
|
||
### Mode A : “ce device devient un pair”
|
||
Composants UI
|
||
- Générer UUID pair
|
||
- Afficher liste de mots BIP32 dérivée de l’UUID
|
||
- Bouton “continuer” (confirmation)
|
||
|
||
Traitements locaux
|
||
- Conversion UUID → chemin BIP32 → mots
|
||
- Enregistrement local du pair
|
||
|
||
### Mode B : “associer un pair existant”
|
||
Composants UI
|
||
- Saisie des mots BIP32 affichés par l’autre device
|
||
- Bouton “reconstituer UUID”
|
||
|
||
Traitements locaux
|
||
- Mots → reconstitution UUID
|
||
- Vérification checksum
|
||
- Enregistrement pair
|
||
|
||
### Publication
|
||
- Préparation des messages nécessaires pour lier pair ↔ membre :
|
||
- message métier (sans signature, sans clés)
|
||
- puis message(s) de signature
|
||
- puis message(s) de déchiffrement si requis
|
||
|
||
### États / erreurs
|
||
- Mots invalides / ordre incorrect
|
||
- Pair déjà présent
|
||
- Membre cible absent du cache (sync requise)
|
||
|
||
## Écran “sélection membre”
|
||
|
||
### Objectif
|
||
Choisir le membre concerné par le login (quand plusieurs membres existent).
|
||
|
||
### Pré-requis
|
||
Graphe local résolu au moins partiellement.
|
||
|
||
### Composants UI
|
||
- Liste des membres
|
||
- label (si déchiffré)
|
||
- actions parents (dont login)
|
||
- pairs associés
|
||
- Action : sélectionner
|
||
|
||
### États / erreurs
|
||
- Aucun membre avec action login → impossible de se connecter
|
||
|
||
## Écran “sélection service pour connexion”
|
||
|
||
### Objectif
|
||
Choisir le service cible du login.
|
||
|
||
### Pré-requis
|
||
Services connus.
|
||
|
||
### Composants UI
|
||
- Liste des services + statuts
|
||
- Bouton “continuer”
|
||
|
||
### États / erreurs
|
||
- Service invalide → alerte + détails
|
||
|
||
## Écran “construction du chemin login”
|
||
|
||
### Objectif
|
||
Résoudre et afficher le chemin de validation du login, et calculer les signatures attendues.
|
||
|
||
### Composants UI
|
||
- Résumé du chemin :
|
||
- service UUID
|
||
- contrat(s) UUID
|
||
- action login UUID
|
||
- membre UUID
|
||
- pairs attendus UUID
|
||
- Tableau “signatures requises” :
|
||
- validateurs
|
||
- règles (qui doit signer)
|
||
- statut (manquante/reçue/valide/invalide)
|
||
- Boutons :
|
||
- Synchroniser (si incomplet)
|
||
- Démarrer login
|
||
|
||
### Traitements locaux
|
||
- Résolution parents
|
||
- Validation validateurs de l’action login
|
||
- Détermination du set minimal de signatures pour satisfaire la règle
|
||
|
||
### États / erreurs
|
||
- Contrat incomplet
|
||
- Validateurs impossibles à satisfaire (ex : pair manquant)
|
||
|
||
## Écran “message de login à valider”
|
||
|
||
### Objectif
|
||
Construire le Message à valider de login.
|
||
|
||
### Composants UI
|
||
- Résumé public :
|
||
- service UUID
|
||
- type UUID
|
||
- timestamp
|
||
- relais cibles
|
||
- Paramètres anti-rejeu :
|
||
- nonce généré (affichage possible en mode avancé)
|
||
- Bouton “signer”
|
||
|
||
### Traitements locaux
|
||
- Construction MessageBase
|
||
- Insertion datajson public minimal (services UUID, types UUID)
|
||
- Calcul hash canonique
|
||
- Préparation du message chiffré
|
||
- Préparation publication “message d’abord”
|
||
|
||
### États / erreurs
|
||
- Format JSON non canonique détecté
|
||
- Relais indisponibles
|
||
|
||
## Écran “collecte des signatures (mFA)”
|
||
|
||
### Objectif
|
||
Obtenir toutes les signatures obligatoires attendues pour l’action login.
|
||
|
||
### Composants UI
|
||
- Liste des signatures requises :
|
||
- clé publique attendue
|
||
- pair/membre associé
|
||
- état
|
||
- Boutons :
|
||
- Signer avec ce device
|
||
- Demander signature sur autre pair
|
||
- Rafraîchir (fetch signatures)
|
||
- Voir détail signature
|
||
|
||
### Flux “signature locale”
|
||
- Calcul signature secp256k1
|
||
- Création Message de signature
|
||
|
||
### Flux “signature distante”
|
||
- Afficher un paquet de demande (hash + contexte)
|
||
- Autre device signe et publie
|
||
- Ce device fetch la signature et rattache
|
||
|
||
### États / erreurs
|
||
- Signature invalide
|
||
- Nonce déjà utilisé (anti-rejeu)
|
||
- Délai d’attente dépassé
|
||
|
||
## Écran “publication du login”
|
||
|
||
### Objectif
|
||
Publier la preuve en respectant la séparation :
|
||
message chiffré → signatures → clés de déchiffrement.
|
||
|
||
### Composants UI
|
||
- Liste des relais + état :
|
||
- envoyé / confirmé / échec
|
||
- Hash final de la preuve
|
||
- Boutons :
|
||
- Publier
|
||
- Republier sur relais manquants
|
||
- Afficher diagnostics
|
||
|
||
### Traitements réseau (ordre strict)
|
||
- POST message chiffré (sans signatures, sans clés)
|
||
- POST message(s) de signature
|
||
- POST message(s) individuels de déchiffrement (si requis)
|
||
|
||
### États / erreurs
|
||
- Message publié mais signatures non publiées → preuve incomplète
|
||
- Signatures publiées mais clés manquantes → preuve inutilisable par tiers
|
||
|
||
## Écran “résultat de connexion”
|
||
|
||
### Objectif
|
||
Afficher un verdict explicite et traçable.
|
||
|
||
### États possibles
|
||
- Connexion acceptée
|
||
- Connexion refusée : contrat incomplet
|
||
- Connexion refusée : signatures insuffisantes
|
||
- Connexion refusée : signatures invalides
|
||
- Connexion refusée : pairing non satisfait
|
||
- Connexion refusée : anti-rejeu (nonce déjà vu / timestamp hors fenêtre)
|
||
- Connexion refusée : objets manquants
|
||
|
||
### Composants UI
|
||
- Statut final
|
||
- Hash de la preuve
|
||
- Service UUID
|
||
- Détails :
|
||
- signatures requises vs obtenues
|
||
- objets manquants
|
||
- logs (mode avancé)
|
||
- Actions :
|
||
- Recommencer
|
||
- Resync
|
||
- Diagnostic
|
||
|
||
## Écran “diagnostic avancé (hash / objet)”
|
||
|
||
### Objectif
|
||
Aider à comprendre un échec (objet manquant, clé absente, signature invalide).
|
||
|
||
### Composants UI
|
||
- Entrée hash (ou sélection depuis liste)
|
||
- Détails objet :
|
||
- type UUID
|
||
- service UUID
|
||
- timestamp
|
||
- statut déchiffrement : OK/non
|
||
- statut signature : OK/non
|
||
- Boutons :
|
||
- Fetch signatures
|
||
- Fetch clés
|
||
- Vérifier canonisation JSON
|
||
- Vérifier validateurs
|
||
|
||
### Erreurs typiques affichées
|
||
- Hash recalculé ≠ hash déclaré
|
||
- Signature secp256k1 invalide
|
||
- Clé publique non autorisée par validateurs
|
||
- Matériel DH absent / non exploitable
|
||
- Parents UUID absents
|
||
|
||
## Écran “synchronisation continue par service”
|
||
|
||
### Objectif
|
||
Maintenir le cache à jour périodiquement, par service.
|
||
|
||
### Composants UI
|
||
- Liste services + toggle sync automatique
|
||
- Fréquence (min/heure/jour)
|
||
- Fenêtre de scan
|
||
- Accélérateurs :
|
||
- Bloom filter : taille, faux positifs estimés
|
||
- Merkle : segments/périodes
|
||
- Bouton “lancer maintenant”
|
||
|
||
### Traitements locaux
|
||
- GET messages depuis dernier checkpoint
|
||
- Dédup hash
|
||
- Fetch signatures et clés si nécessaire
|
||
- Validation graphe et droits
|
||
|
||
### États / erreurs
|
||
- Volume trop important → recommander Bloom/Merkle
|
||
- Relais instables → backoff
|
||
|
||
## Écran “paramètres crypto (avancé)”
|
||
|
||
### Objectif
|
||
Afficher et régler les politiques crypto et compatibilité.
|
||
|
||
### Composants UI
|
||
- Algorithme hash (ex : sha256)
|
||
- Canonisation JSON (mode strict)
|
||
- Paramètres ECDH (secp256k1)
|
||
- Paramètres KDF/symétrique (si exposés)
|
||
- Politique anti-rejeu :
|
||
- TTL nonce
|
||
- fenêtre timestamp
|
||
|
||
### États / erreurs
|
||
- Incompatibilité avec services existants
|
||
- Paramètres non supportés par version logicielle
|
||
|
||
# Machine à états du login sans serveur central (secp256k1 + contrats + pairing mFA)
|
||
|
||
## Objectif
|
||
|
||
Décrire une machine à états déterministe et implémentable pour :
|
||
- créer/importer une identité,
|
||
- synchroniser des messages via relais (pull-only),
|
||
- résoudre le graphe contractuel,
|
||
- imposer le pairing (mFA),
|
||
- construire un message de login à valider,
|
||
- collecter et vérifier les signatures attendues,
|
||
- publier la preuve (message → signatures → clés),
|
||
- obtenir un verdict local côté client et côté service (sans autorité centrale).
|
||
|
||
## Définitions globales
|
||
|
||
### Notation
|
||
|
||
- État : `S_*`
|
||
- Événement : `E_*`
|
||
- Garde (condition) : `G_*`
|
||
- Action (effet) : `A_*`
|
||
- Erreur : `X_*`
|
||
|
||
### Règles d’adressage et de contenu
|
||
|
||
- Tout objet est adressé par `Hash(JSON_canonique(objet))`
|
||
- `JSON_canonique(objet)` = JSON sans :
|
||
- `hash`
|
||
- `signatures`
|
||
- `clefs_de_chiffrement`
|
||
- Les signatures et les clés sont récupérées séparément après `GET message`.
|
||
- Tout est publié pour tous (sans destinataire explicite), chiffré.
|
||
|
||
### Objets de preuve
|
||
|
||
- `MsgChiffre` : `{ hash, message_chiffre, datajson_public }`
|
||
- `MsgSignature` : `{ signature: {hash, pubkey, sig, nonce, materiel} }`
|
||
- `MsgCle` : `{ hash_message, cle_chiffrement, df_ecdh_scannable }`
|
||
|
||
### Fenêtres de synchronisation
|
||
|
||
- `T0 = date_anniversaire_creation_cles`
|
||
- `T_last = dernier_checkpoint_local`
|
||
- Scan par défaut : `[T_last ou T0 ; maintenant]`
|
||
|
||
### Cache local minimal
|
||
|
||
- `cache_hash_vus`
|
||
- `index_par_service_uuid`
|
||
- `index_par_type_uuid`
|
||
- `index_par_hash -> (msg, signatures?, cles?, statut_dechiffrement, statut_validation)`
|
||
- `index_pairs_locaux`
|
||
- `index_membres_connus`
|
||
- `index_ecdh` (si ECDH structuré par pubkeys)
|
||
|
||
## Variables de session (runtime)
|
||
|
||
- `service_cible_uuid`
|
||
- `membre_cible_uuid`
|
||
- `action_login_uuid`
|
||
- `pairs_attendus[]`
|
||
- `signatures_requises[]`
|
||
- `nonce_login`
|
||
- `hash_login`
|
||
- `msg_login_chiffre`
|
||
- `relays[]`
|
||
- `timer_deadlines` (réseau, collecte signatures, fetch clés)
|
||
|
||
## États et transitions
|
||
|
||
## S_INIT (démarrage application)
|
||
|
||
### Entrée
|
||
- Charger cache local
|
||
- Charger identité locale si présente
|
||
- Charger configuration relais
|
||
|
||
### Événements sortants
|
||
- `E_IDENTITY_ABSENT` → `S_IDENTITY_REQUIRED`
|
||
- `E_IDENTITY_PRESENT` → `S_HOME`
|
||
|
||
---
|
||
|
||
## S_IDENTITY_REQUIRED (identité manquante)
|
||
|
||
### UI associée
|
||
- écran accueil avec options “Créer” / “Importer”
|
||
|
||
### Transitions
|
||
- `E_CREATE_IDENTITY` → `S_IDENTITY_CREATE`
|
||
- `E_IMPORT_IDENTITY` → `S_IDENTITY_IMPORT`
|
||
|
||
---
|
||
|
||
## S_IDENTITY_CREATE (création identité locale)
|
||
|
||
### Actions
|
||
- `A_GEN_SECP256K1_KEYPAIR`
|
||
- `A_SET_T0_ANNIVERSAIRE`
|
||
- `A_INIT_CACHE`
|
||
|
||
### Sorties
|
||
- `E_IDENTITY_CREATED` → `S_HOME`
|
||
|
||
### Erreurs
|
||
- `X_RNG_UNAVAILABLE` → `S_ERROR_FATAL`
|
||
|
||
---
|
||
|
||
## S_IDENTITY_IMPORT (import identité)
|
||
|
||
### Actions
|
||
- `A_PARSE_SEED_OR_PRIVKEY`
|
||
- `A_DERIVE_PUBKEY`
|
||
- `A_SET_OR_CONFIRM_T0`
|
||
- `A_INIT_CACHE`
|
||
|
||
### Sorties
|
||
- `E_IDENTITY_IMPORTED` → `S_HOME`
|
||
|
||
### Erreurs
|
||
- `X_IMPORT_INVALID` → `S_ERROR_RECOVERABLE`
|
||
|
||
---
|
||
|
||
## S_HOME (accueil)
|
||
|
||
### Événements
|
||
- `E_OPEN_RELAY_SETTINGS` → `S_RELAY_SETTINGS`
|
||
- `E_SYNC_NOW` → `S_SYNC_GLOBAL`
|
||
- `E_MANAGE_PAIRS` → `S_PAIR_MANAGEMENT`
|
||
- `E_LOGIN_START` → `S_LOGIN_SELECT_SERVICE`
|
||
|
||
### Gardes
|
||
- `G_IDENTITY_PRESENT` sinon retour `S_IDENTITY_REQUIRED`
|
||
|
||
---
|
||
|
||
## S_RELAY_SETTINGS (configuration relais)
|
||
|
||
### Actions
|
||
- `A_SAVE_RELAYS_CONFIG`
|
||
- `A_TEST_RELAYS` (optionnel)
|
||
|
||
### Sorties
|
||
- `E_RELAYS_SAVED` → `S_HOME`
|
||
- `E_CANCEL` → `S_HOME`
|
||
|
||
### Erreurs
|
||
- `X_RELAYS_INVALID` → `S_ERROR_RECOVERABLE`
|
||
|
||
---
|
||
|
||
## S_SYNC_GLOBAL (synchronisation globale)
|
||
|
||
### Objectif
|
||
Récupérer `MsgChiffre`, dédupliquer par hash, puis fetch clés et signatures sur demande.
|
||
|
||
### Entrée
|
||
- Déterminer fenêtre `[T_scan_start; T_scan_end]`
|
||
- Initialiser compteurs
|
||
|
||
### Actions boucle (pull)
|
||
- `A_GET_MSGS_CHIFFRES(relays, window)` → liste `{hash, message_chiffre, datajson_public}`
|
||
- `A_DEDUP_HASH(cache_hash_vus)`
|
||
- `A_INDEX_PUBLIC_METADATA(service_uuid, type_uuid, timestamp)`
|
||
- `A_DETECT_POTENTIEL_DECHIFFRABLE(index_ecdh, datajson_public)` (heuristique)
|
||
- `A_FETCH_KEYS_BY_HASH(hash)` (si candidat)
|
||
- `A_TRY_DECRYPT(hash)` (si clé présente)
|
||
- `A_RECALC_CANONICAL_HASH`
|
||
- `A_FETCH_SIGNATURES_BY_HASH(hash)` (si déchiffré)
|
||
- `A_VERIFY_SIGNATURES`
|
||
- `A_UPDATE_GRAPH_CACHE`
|
||
|
||
### Sorties
|
||
- `E_SYNC_DONE` → `S_HOME`
|
||
- `E_SYNC_DONE_WITH_DISCOVERY` → `S_SERVICE_LIST`
|
||
|
||
### Erreurs récupérables
|
||
- `X_RELAY_TIMEOUT` → rester `S_SYNC_GLOBAL` avec backoff
|
||
- `X_DECRYPT_KEY_MISSING` → marquer état local “indéchiffrable”
|
||
- `X_SIG_MISSING` → marquer “non validé”
|
||
- `X_HASH_MISMATCH` → marquer “corrompu / non conforme”
|
||
|
||
---
|
||
|
||
## S_SERVICE_LIST (liste services)
|
||
|
||
### Entrée
|
||
- Charger services connus depuis `index_par_service_uuid`
|
||
|
||
### Transitions
|
||
- `E_SELECT_SERVICE(service_uuid)` → `S_LOGIN_SELECT_MEMBER` (ou direct si membre unique)
|
||
- `E_RESYNC_SERVICE(service_uuid)` → `S_SYNC_SERVICE`
|
||
- `E_BACK` → `S_HOME`
|
||
|
||
---
|
||
|
||
## S_SYNC_SERVICE (sync ciblée service)
|
||
|
||
### Actions
|
||
- `A_GET_MSGS_CHIFFRES(filter=service_uuid)`
|
||
- mêmes actions de déchiffrement/validation que `S_SYNC_GLOBAL`
|
||
|
||
### Sorties
|
||
- `E_SYNC_SERVICE_DONE` → `S_SERVICE_LIST`
|
||
- `E_BACK` → `S_SERVICE_LIST`
|
||
|
||
---
|
||
|
||
## S_PAIR_MANAGEMENT (gestion pairs)
|
||
|
||
### Transitions
|
||
- `E_PAIR_ADD` → `S_PAIR_ADD`
|
||
- `E_PAIR_ASSOCIATE_TO_MEMBER` → `S_PAIR_ASSOCIATE`
|
||
- `E_BACK` → `S_HOME`
|
||
|
||
---
|
||
|
||
## S_PAIR_ADD (ajout d’un pair)
|
||
|
||
### Modes
|
||
- local : “ce device devient un pair”
|
||
- distant : “associer un pair existant”
|
||
|
||
### Actions
|
||
- `A_GEN_PAIR_UUID` (mode local)
|
||
- `A_UUID_TO_BIP32_WORDS` (affichage)
|
||
- `A_WORDS_TO_UUID` (saisie)
|
||
- `A_STORE_PAIR_LOCAL`
|
||
|
||
### Sorties
|
||
- `E_PAIR_READY` → `S_PAIR_ASSOCIATE`
|
||
|
||
### Erreurs
|
||
- `X_WORDS_INVALID` → `S_ERROR_RECOVERABLE`
|
||
|
||
---
|
||
|
||
## S_PAIR_ASSOCIATE (associer pair ↔ membre)
|
||
|
||
### Gardes
|
||
- `G_MEMBRE_EXISTS_LOCALLY` sinon `S_SYNC_GLOBAL`
|
||
|
||
### Actions (préparation publication)
|
||
- `A_BUILD_PAIR_MEMBERSHIP_MESSAGE` (message métier sans signatures/clefs)
|
||
- `A_ENCRYPT_MESSAGE`
|
||
- `A_CALC_HASH`
|
||
- `A_QUEUE_PUBLISH_MESSAGE`
|
||
- `A_QUEUE_PUBLISH_SIGNATURES_REQUIRED`
|
||
- `A_QUEUE_PUBLISH_KEYS_IF_REQUIRED`
|
||
|
||
### Sorties
|
||
- `E_ASSOCIATION_QUEUED` → `S_PUBLISH_QUEUE`
|
||
|
||
---
|
||
|
||
## S_PUBLISH_QUEUE (file de publication)
|
||
|
||
### Objectif
|
||
Publier dans l’ordre strict : message → signatures → clés.
|
||
|
||
### Actions
|
||
- `A_POST_MSG_CHIFFRE`
|
||
- `A_POST_MSG_SIGNATURES`
|
||
- `A_POST_MSG_KEYS`
|
||
|
||
### Sorties
|
||
- `E_PUBLISH_OK` → `S_HOME`
|
||
- `E_PUBLISH_PARTIAL` → `S_ERROR_RECOVERABLE`
|
||
|
||
### Erreurs
|
||
- `X_RELAY_DOWN` → `S_ERROR_RECOVERABLE`
|
||
|
||
---
|
||
|
||
## S_LOGIN_SELECT_SERVICE (début login : choix service)
|
||
|
||
### Gardes
|
||
- `G_PAIRING_SATISFIED` sinon `S_LOGIN_PAIRING_REQUIRED`
|
||
|
||
### Transitions
|
||
- `E_SELECT_SERVICE(service_uuid)` → `S_LOGIN_SELECT_MEMBER`
|
||
- `E_BACK` → `S_HOME`
|
||
|
||
---
|
||
|
||
## S_LOGIN_PAIRING_REQUIRED (pairing obligatoire)
|
||
|
||
### Transitions
|
||
- `E_GO_PAIRING` → `S_PAIR_MANAGEMENT`
|
||
- `E_BACK` → `S_HOME`
|
||
|
||
---
|
||
|
||
## S_LOGIN_SELECT_MEMBER (choix membre)
|
||
|
||
### Gardes
|
||
- `G_MEMBRE_WITH_ACTION_LOGIN_EXISTS` sinon `S_ERROR_RECOVERABLE`
|
||
|
||
### Transitions
|
||
- `E_SELECT_MEMBER(membre_uuid)` → `S_LOGIN_BUILD_PATH`
|
||
- `E_BACK` → `S_SERVICE_LIST`
|
||
|
||
---
|
||
|
||
## S_LOGIN_BUILD_PATH (résolution graphe et validateurs)
|
||
|
||
### Actions
|
||
- `A_RESOLVE_GRAPH(service_uuid, membre_uuid)`
|
||
- service → contrat → champ → action(login) → membre → pairs
|
||
- `A_VALIDATE_PARENTS_UUID_CONSTRAINTS`
|
||
- `A_VALIDATE_TYPES_NAMES_IF_AVAILABLE`
|
||
- `A_LOAD_ACTION_VALIDATORS`
|
||
- `A_COMPUTE_REQUIRED_SIGNATURES_SET`
|
||
|
||
### Sorties
|
||
- `E_PATH_OK` → `S_LOGIN_CHECK_PAIRS`
|
||
- `E_PATH_INCOMPLETE` → `S_ERROR_RECOVERABLE`
|
||
- `E_PATH_INVALID` → `S_ERROR_RECOVERABLE`
|
||
|
||
### Erreurs
|
||
- `X_PARENT_MISSING`
|
||
- `X_VALIDATORS_UNSATISFIABLE`
|
||
- `X_HASH_MISMATCH`
|
||
|
||
---
|
||
|
||
## S_LOGIN_CHECK_PAIRS (vérifier pairs attendus)
|
||
|
||
### Gardes
|
||
- `G_ALL_REQUIRED_PAIRS_AVAILABLE` sinon `S_LOGIN_NEED_MORE_PAIRS`
|
||
|
||
### Sorties
|
||
- `E_PAIRS_OK` → `S_LOGIN_BUILD_CHALLENGE`
|
||
|
||
---
|
||
|
||
## S_LOGIN_NEED_MORE_PAIRS (pairs manquants)
|
||
|
||
### Transitions
|
||
- `E_ADD_PAIR` → `S_PAIR_MANAGEMENT`
|
||
- `E_RESYNC` → `S_SYNC_SERVICE`
|
||
- `E_BACK` → `S_SERVICE_LIST`
|
||
|
||
---
|
||
|
||
## S_LOGIN_BUILD_CHALLENGE (construction message à valider)
|
||
|
||
### Actions
|
||
- `A_GENERATE_NONCE`
|
||
- `A_BUILD_MESSAGEBASE_LOGIN`
|
||
- services_uuid = service_cible_uuid
|
||
- types_uuid = type_login_uuid
|
||
- timestamp = now
|
||
- relays = relays[]
|
||
- version logicielle
|
||
- `A_ENCRYPT_LOGIN_MESSAGE`
|
||
- `A_CANONICALIZE_JSON`
|
||
- `A_CALC_HASH_LOGIN`
|
||
|
||
### Sorties
|
||
- `E_CHALLENGE_READY` → `S_LOGIN_COLLECT_SIGNATURES`
|
||
|
||
### Erreurs
|
||
- `X_CANONICALIZATION_FAIL`
|
||
- `X_ENCRYPT_FAIL`
|
||
|
||
---
|
||
|
||
## S_LOGIN_COLLECT_SIGNATURES (collecte signatures mFA)
|
||
|
||
### Objectif
|
||
Obtenir toutes les signatures imposées par validateurs.
|
||
|
||
### Sous-états internes (recommandé)
|
||
- `S_LOGIN_SIG_LOCAL`
|
||
- `S_LOGIN_SIG_REMOTE_WAIT`
|
||
- `S_LOGIN_SIG_FETCH`
|
||
|
||
### Actions
|
||
- `A_SIGN_LOCAL(hash_login, privkey_pair_local)` → MsgSignature
|
||
- `A_REQUEST_REMOTE_SIGNATURE(hash_login, context)` (UI/QR/mots selon design)
|
||
- `A_FETCH_SIGNATURES_BY_HASH(hash_login)`
|
||
- `A_VERIFY_SIGNATURES_SECP256K1`
|
||
- `A_CHECK_VALIDATORS_SATISFIED`
|
||
|
||
### Sorties
|
||
- `E_SIGNATURES_COMPLETE` → `S_LOGIN_PUBLISH_PROOF`
|
||
- `E_SIGNATURES_INCOMPLETE` → rester `S_LOGIN_COLLECT_SIGNATURES`
|
||
|
||
### Erreurs
|
||
- `X_SIGNATURE_INVALID`
|
||
- `X_SIGNATURE_TIMEOUT`
|
||
- `X_NONCE_REUSED` (si cache nonce)
|
||
- `X_PUBKEY_NOT_AUTHORIZED`
|
||
|
||
---
|
||
|
||
## S_LOGIN_PUBLISH_PROOF (publication preuve login)
|
||
|
||
### Ordre strict
|
||
1) publier message chiffré sans signatures ni clés
|
||
2) publier message(s) de signature
|
||
3) publier message(s) de déchiffrement si nécessaire
|
||
|
||
### Actions
|
||
- `A_POST_MSG_CHIFFRE(hash_login, msg_login_chiffre)`
|
||
- `A_POST_SIGNATURES(hash_login, signatures[])`
|
||
- `A_POST_KEYS_IF_REQUIRED(hash_login, key_materials[])`
|
||
|
||
### Sorties
|
||
- `E_PUBLISH_LOGIN_OK` → `S_LOGIN_VERIFY_LOCAL`
|
||
- `E_PUBLISH_LOGIN_PARTIAL` → `S_ERROR_RECOVERABLE`
|
||
|
||
### Erreurs
|
||
- `X_RELAY_POST_FAIL`
|
||
|
||
---
|
||
|
||
## S_LOGIN_VERIFY_LOCAL (vérification locale finale)
|
||
|
||
### Objectif
|
||
Le client démontre que la preuve est auto-cohérente et satisfaisante avant affichage.
|
||
|
||
### Actions
|
||
- `A_RELOAD_PUBLISHED_OBJECTS_IF_NEEDED`
|
||
- `A_VERIFY_CANONICAL_HASH(hash_login)`
|
||
- `A_VERIFY_SIGNATURES`
|
||
- `A_VERIFY_GRAPH_CONFORMITY`
|
||
- `A_VERIFY_ANTI_REPLAY(nonce, timestamp_window)`
|
||
|
||
### Sorties
|
||
- `E_LOCAL_VERDICT_ACCEPT` → `S_LOGIN_SUCCESS`
|
||
- `E_LOCAL_VERDICT_REJECT` → `S_LOGIN_FAILURE`
|
||
|
||
---
|
||
|
||
## S_LOGIN_SUCCESS (connexion OK)
|
||
|
||
### Sorties
|
||
- `E_DONE` → `S_HOME`
|
||
|
||
---
|
||
|
||
## S_LOGIN_FAILURE (connexion KO)
|
||
|
||
### Actions
|
||
- Afficher diagnostics : signatures manquantes, objets manquants, anti-rejeu, etc.
|
||
|
||
### Sorties
|
||
- `E_RETRY` → `S_LOGIN_BUILD_PATH` (ou `S_LOGIN_COLLECT_SIGNATURES` selon cause)
|
||
- `E_RESYNC` → `S_SYNC_SERVICE`
|
||
- `E_BACK` → `S_HOME`
|
||
|
||
---
|
||
|
||
## États d’erreur
|
||
|
||
## S_ERROR_RECOVERABLE (erreur récupérable)
|
||
|
||
### Objectif
|
||
Afficher une erreur explicite et proposer des actions de reprise.
|
||
|
||
### Sorties possibles
|
||
- `E_RETRY` → état précédent
|
||
- `E_SYNC_NOW` → `S_SYNC_GLOBAL`
|
||
- `E_OPEN_DIAGNOSTIC` → `S_DIAGNOSTIC`
|
||
- `E_BACK` → `S_HOME`
|
||
|
||
---
|
||
|
||
## S_ERROR_FATAL (erreur bloquante)
|
||
|
||
### Objectif
|
||
Cas impossible à corriger sans intervention externe (ex : RNG indisponible).
|
||
|
||
### Sorties
|
||
- `E_EXIT` → fin
|
||
|
||
---
|
||
|
||
## S_DIAGNOSTIC (diagnostic hash / objet)
|
||
|
||
### Actions
|
||
- `A_FETCH_MSG_BY_HASH`
|
||
- `A_FETCH_SIGNATURES_BY_HASH`
|
||
- `A_FETCH_KEYS_BY_HASH`
|
||
- `A_TRY_DECRYPT`
|
||
- `A_VERIFY_HASH`
|
||
- `A_VERIFY_SIGNATURES`
|
||
- `A_VERIFY_VALIDATORS`
|
||
|
||
### Sorties
|
||
- `E_BACK` → `S_HOME` (ou état appelant)
|
||
|
||
## Anti-rejeu et cohérence temporelle (contrainte transversale)
|
||
|
||
### Règles
|
||
- Un login doit inclure un `nonce_login` unique.
|
||
- Le service (ou le validateur final) doit maintenir un cache `nonce_vus` par fenêtre temporelle.
|
||
- Le client doit également maintenir un cache local pour éviter de republier un nonce déjà utilisé.
|
||
|
||
### Erreurs
|
||
- `X_NONCE_REUSED` : nonce déjà vu → rejet.
|
||
- `X_TIMESTAMP_OUT_OF_WINDOW` : timestamp trop ancien/futur → rejet.
|
||
|
||
## Optimisation de scan (optionnel)
|
||
|
||
### Bloom filter
|
||
- État utilisateur : activé/désactivé
|
||
- Effet : éviter de re-fetch massivement des hash déjà vus
|
||
- Limite : faux positifs → toujours confirmer par vérification hash
|
||
|
||
### Merkle trees
|
||
- État utilisateur : activé/désactivé
|
||
- Effet : synchroniser par segments et preuves d’inclusion
|
||
- Limite : complexité de maintenance côté relais
|
||
|
||
## Résumé des sorties réseau par phase
|
||
|
||
### Synchronisation
|
||
- GET `MsgChiffre` (par fenêtre temporelle, éventuellement par service)
|
||
- GET `MsgCle` par hash (ciblé)
|
||
- GET `MsgSignature` par hash (ciblé)
|
||
|
||
### Publication preuve (ordre strict)
|
||
- POST `MsgChiffre` (sans signatures ni clés)
|
||
- POST `MsgSignature`
|
||
- POST `MsgCle` (si requis)
|
||
|
||
## Table des causes d’échec et état de reprise conseillé
|
||
|
||
- Contrat incomplet → `S_SYNC_SERVICE` puis `S_LOGIN_BUILD_PATH`
|
||
- Parent UUID manquant → `S_SYNC_GLOBAL` puis `S_LOGIN_BUILD_PATH`
|
||
- Message indéchiffrable (clé manquante) → `S_SYNC_GLOBAL` + fetch clés → retry
|
||
- Signature manquante → `S_LOGIN_COLLECT_SIGNATURES` + fetch signatures → retry
|
||
- Signature invalide → rester `S_LOGIN_COLLECT_SIGNATURES` (recollect)
|
||
- Pubkey non autorisée → `S_LOGIN_BUILD_PATH` (recalcul validateurs)
|
||
- Nonce rejoué → `S_LOGIN_BUILD_CHALLENGE` (nouveau nonce)
|
||
- Relais down → `S_RELAY_SETTINGS` ou `S_PUBLISH_QUEUE` avec retry/backoff
|
||
|
||
# Catalogue des objets du projet (contrats, identité, pairing, login, relais)
|
||
|
||
## Portée
|
||
|
||
Ce document recense l’ensemble des objets manipulés par le protocole :
|
||
- structure des contrats et des entités (service, contrat, champ, action, membre, pair),
|
||
- structure commune de message (MessageBase, hash, signature),
|
||
- objets de validation (validateurs, message à valider),
|
||
- objets cryptographiques séparés (message de signature, message individuel de déchiffrement),
|
||
- enveloppes réseau (messages chiffrés publiés sur relais),
|
||
- contraintes de publication et de récupération.
|
||
|
||
La règle principale est la séparation stricte :
|
||
- publication du message sans signatures ni clés,
|
||
- publication des signatures ensuite,
|
||
- publication des clés/matériels de déchiffrement ensuite.
|
||
|
||
## Conventions et invariants
|
||
|
||
### Types (types uuid et types names chiffrés)
|
||
Chaque objet porte un `types_uuid` et un `types_names_chiffres` incluant au minimum le type de l’objet.
|
||
Le type name est chiffré et peut inclure des sous-types (ex : "login" pour ActionLogin).
|
||
|
||
### Hash canonique
|
||
Le `hash` est calculé sur le JSON canonique de l’objet :
|
||
- sans le champ `hash`,
|
||
- sans la liste `signatures`,
|
||
- sans les champs `cles_de_chiffrement` (ou équivalents),
|
||
- sans tout bloc de signature ou matériel crypto posté séparément.
|
||
|
||
Le hash doit spécifier explicitement l’algorithme.
|
||
|
||
### Signature secp256k1
|
||
Les signatures servent à prouver :
|
||
- l’intégrité (le hash),
|
||
- l’autorité (clé publique autorisée par validateurs),
|
||
- l’anti-rejeu (nonce / matériel additionnel éventuel).
|
||
|
||
### Publication “pour tous”
|
||
Tous les messages sont publiés :
|
||
- sans destinataire explicite,
|
||
- sous forme chiffrée,
|
||
- récupérés par GET périodiques via relais.
|
||
|
||
### Récupération séparée
|
||
Un GET de message ne doit pas renvoyer automatiquement :
|
||
- signatures,
|
||
- clés/matériels de déchiffrement.
|
||
Ils sont récupérés par requêtes dédiées ensuite.
|
||
|
||
## Structure commune : MessageBase
|
||
|
||
### Rôle
|
||
Base obligatoire d’un message de l’écosystème.
|
||
Supporte l’adressage (hash), l’indexation (uuid, version, type, service), et la synchronisation (timestamp, relais).
|
||
|
||
### Champs obligatoires
|
||
- `uuid` : identifiant unique de l’objet
|
||
- `version` : version du schéma de cet objet
|
||
- `types` :
|
||
- `types_uuid` : identifiant de type
|
||
- `types_names_chiffres` : au minimum le type (ex : "pair", "membre", "contrat")
|
||
- `cles_de_chiffrement` : paramètres + algorithmes (présents dans le message complet, mais exclus du hash canonique)
|
||
- `datajson` :
|
||
- obligatoires :
|
||
- `services_uuid[]` : au moins 1
|
||
- `types_uuid[]` : au moins 1
|
||
- optionnels :
|
||
- `label`
|
||
- `description_longue`
|
||
- `description_courte`
|
||
- `photo`
|
||
- `image`
|
||
- `banniere`
|
||
- `url`
|
||
- `paragraphes[]` : couples texte + image
|
||
- `tarif`
|
||
- `timestamp` : horodatage
|
||
- `liste_relais[]` : liste de relais (IP / endpoints)
|
||
- `version_logicielle` : version du client ayant produit le message
|
||
|
||
### Champs dérivés / attachés après coup
|
||
- `hash` : hash canonique (stockable dans le message complet, mais calculé sans certains champs)
|
||
- `signatures[]` : non inclus dans le message publié initialement (posté séparément)
|
||
|
||
## Objet : Hash
|
||
|
||
### Rôle
|
||
Décrit le hash canonique d’un objet.
|
||
|
||
### Champs
|
||
- `algo` : nom de l’algorithme (ex : sha256)
|
||
- `hash_value` : valeur du hash (encodage à spécifier)
|
||
|
||
### Calcul
|
||
Le hash porte sur le JSON canonique :
|
||
- sans `hash`,
|
||
- sans signatures,
|
||
- sans clés de chiffrement.
|
||
|
||
## Objet : Signature
|
||
|
||
### Rôle
|
||
Preuve cryptographique associée à un hash.
|
||
|
||
### Champs
|
||
- `hash` : hash signé (référence)
|
||
- `cle_publique` : clé publique secp256k1
|
||
- `signature` : signature cryptographique secp256k1
|
||
- `nonce` : anti-rejeu
|
||
- `materiel` : champs optionnels (ex : contexte, challenge, metadata anti-rejeu)
|
||
|
||
### Contraintes
|
||
- La clé publique doit être autorisée selon les validateurs du message et/ou de l’action.
|
||
- Le nonce doit être unique dans la fenêtre de validité considérée.
|
||
|
||
## Objet : Message à valider
|
||
|
||
### Rôle
|
||
Enveloppe logique d’un message nécessitant validation contractuelle.
|
||
|
||
### Composition
|
||
- `MessageBase`
|
||
- `validateurs`
|
||
|
||
### Finalité
|
||
Permet de déterminer :
|
||
- quelles signatures sont requises,
|
||
- qui a autorité pour signer,
|
||
- quelles dépendances de signatures sont nécessaires.
|
||
|
||
## Objet : Validateurs
|
||
|
||
### Rôle
|
||
Définir les exigences de signatures, sous forme de règles par rôle/membre.
|
||
|
||
### Champs
|
||
- `membres_du_role[]` : au moins 1
|
||
|
||
Pour chaque membre de rôle :
|
||
- `signatures_obligatoires[]` :
|
||
- signatures exigées des autres membres et/ou de lui-même
|
||
- cardinalité minimale (si modèle seuil)
|
||
- dépendances éventuelles
|
||
|
||
### Contraintes
|
||
- La liste des membres du rôle doit être non vide.
|
||
- Les signatures doivent pouvoir être résolues vers des clés publiques présentes dans le graphe (membre/pair).
|
||
|
||
## Objet : Message de signature
|
||
|
||
### Rôle
|
||
Publication séparée d’une ou plusieurs signatures associées à un message.
|
||
|
||
### Champs obligatoires
|
||
- `signature` : structure Signature complète
|
||
|
||
### Indexation recommandée
|
||
- `hash_cible` : hash du message ciblé (si non redondant avec signature.hash)
|
||
|
||
### Cycle de vie
|
||
1) message publié sans signatures
|
||
2) message(s) de signature publiés ensuite et attachés localement au message ciblé
|
||
|
||
## Objet : Message individuel de déchiffrement
|
||
|
||
### Rôle
|
||
Publication séparée des éléments permettant de récupérer une clé de déchiffrement (ou une clé enveloppe).
|
||
|
||
### Champs obligatoires
|
||
- `hash_message` : hash du message chiffré concerné
|
||
- `cle_de_chiffrement_message` :
|
||
- clé de chiffrement du message chiffré
|
||
- clé de chiffrement chiffrée (enveloppe)
|
||
- paramètres et algorithmes complets
|
||
- `df_ecdh_scannable` :
|
||
- matériel Diffie-Hellman à scanner
|
||
- contient une clé (ou information) permettant de déchiffrer la clé enveloppe via secret partagé
|
||
|
||
### Contraintes
|
||
- Le matériel DH est inutilisable sans possession d’une clé privée correspondante.
|
||
- Ce message doit pouvoir être filtré/identifié côté client lors d’un scan global.
|
||
|
||
## Objet : Enveloppe réseau “message chiffré publié”
|
||
|
||
### Rôle
|
||
Format minimal publié sur les relais pour la diffusion “pour tous”.
|
||
|
||
### Champs
|
||
- `hash` : hash canonique du message (référence)
|
||
- `message_chiffre` : payload chiffré (opaque)
|
||
- `datajson_public` :
|
||
- métadonnées non sensibles utiles au filtrage
|
||
- doit inclure au minimum :
|
||
- `services_uuid[]`
|
||
- `types_uuid[]`
|
||
- peut inclure :
|
||
- `timestamp`
|
||
- `version`
|
||
- autres marqueurs de routage/filtrage
|
||
|
||
### Contraintes
|
||
- Ne doit pas inclure signatures.
|
||
- Ne doit pas inclure clés de chiffrement.
|
||
|
||
## Objets “contrats / identité”
|
||
|
||
## Objet : Service
|
||
|
||
### Rôle
|
||
Décrit un service, son identité contractuelle, et sert de racine à une authentification.
|
||
|
||
### Champs spécifiques
|
||
- `contrat_uuid` : référence vers un Contrat
|
||
- `types_names_chiffres` inclut "service"
|
||
|
||
### Contraintes
|
||
- Doit exister dans `datajson.services_uuid[]` des objets liés au service.
|
||
- Doit être résoluble via sync par service.
|
||
|
||
## Objet : Contrat
|
||
|
||
### Rôle
|
||
Contrat d’identité principal pour un service.
|
||
|
||
### Champs spécifiques
|
||
- `message_a_valider` : base + validateurs applicables
|
||
- `types_names_chiffres` inclut "contrat"
|
||
|
||
### Contraintes
|
||
- Le contrat doit être déchiffrable et validable pour autoriser des actions.
|
||
|
||
## Objet : Champ
|
||
|
||
### Rôle
|
||
Unité contractuelle rattachée à un ou plusieurs contrats.
|
||
|
||
### Champs spécifiques
|
||
- `message_a_valider`
|
||
- `types_names_chiffres` inclut "champ"
|
||
- `contrats_parents_uuid[]` : au moins 1
|
||
|
||
### Contraintes
|
||
- Au moins un parent contrat.
|
||
- Permet d’étendre la structure du contrat et des exigences.
|
||
|
||
## Objet : Action
|
||
|
||
### Rôle
|
||
Action exécutable dans le contexte du contrat.
|
||
Contient ses propres validateurs.
|
||
|
||
### Champs spécifiques
|
||
- `message_a_valider`
|
||
- `types_names_chiffres` inclut "action"
|
||
- `validateurs_action`
|
||
- `contrats_parents_uuid[]` : au moins 1
|
||
|
||
### Contraintes
|
||
- Au moins un parent contrat.
|
||
- Les validateurs doivent être satisfaisables.
|
||
|
||
## Objet : ActionLogin
|
||
|
||
### Rôle
|
||
Spécialisation de Action, de type “login”.
|
||
|
||
### Champs spécifiques
|
||
- `action` : référence Action
|
||
- `types_names_chiffres` inclut "login"
|
||
|
||
### Contraintes
|
||
- Doit être identifiable comme action de login dans le graphe.
|
||
- Les signatures requises pour login sont tirées des validateurs de l’action.
|
||
|
||
## Objet : Membre
|
||
|
||
### Rôle
|
||
Identité d’un membre (acteur) autorisé à exécuter des actions, dont login.
|
||
|
||
### Champs spécifiques
|
||
- `message_a_valider`
|
||
- `types_names_chiffres` inclut "membre"
|
||
- `actions_parents_uuid[]` : au moins 1
|
||
|
||
### Contraintes
|
||
- Doit référencer au moins une action.
|
||
- Doit pouvoir être lié à un ou plusieurs pairs (devices).
|
||
|
||
## Objet : Pair
|
||
|
||
### Rôle
|
||
Représente un device/instance participant aux signatures (mFA).
|
||
|
||
### Champs spécifiques
|
||
- `MessageBase`
|
||
- `types_names_chiffres` inclut "pair"
|
||
- `membres_parents_uuid[]` : au moins 1
|
||
|
||
### Contraintes
|
||
- Pairing obligatoire : au moins un pair attendu doit être disponible pour login.
|
||
- L’UUID du pair sert d’identifiant uniquement (clé d’identification), pas de secret.
|
||
|
||
## Conversion UUID pair ↔ mots (BIP32)
|
||
|
||
### Rôle
|
||
Procédure robuste d’association pair ↔ membre sans échanger l’UUID brut.
|
||
|
||
### Procédé
|
||
- UUID du pair converti via dérivation BIP32 en une liste de mots.
|
||
- Device A affiche les mots.
|
||
- Device B saisit les mots.
|
||
- Reconstitution de l’UUID du pair.
|
||
|
||
### Contraintes
|
||
- La liste de mots doit inclure un checksum ou mécanisme de détection d’erreur.
|
||
- Les mots n’exposent pas de secret exploitable : l’UUID n’est qu’un identifiant.
|
||
|
||
## Objet : Relais (entité réseau)
|
||
|
||
### Rôle
|
||
Stocker et relayer des objets adressés par hash.
|
||
Assurer une diffusion inter-relais.
|
||
|
||
### Responsabilités minimales
|
||
- Stocker :
|
||
- enveloppes `MsgChiffre`
|
||
- messages `MsgSignature`
|
||
- messages `MsgCle`
|
||
- Relayer entre relais
|
||
- Déduplication :
|
||
- sauvegarder les hash reçus pour ne pas relayer deux fois
|
||
|
||
### Contraintes
|
||
- Un relais ne doit pas “fusionner” message + signatures + clés lors d’un GET.
|
||
- Le client doit pouvoir GET par période et idéalement filtrer par service.
|
||
|
||
## Catalogue des flux (rappel)
|
||
|
||
## Publication d’un objet (ordre strict)
|
||
|
||
1) Publication `MsgChiffre`
|
||
- contient hash + message chiffré + datajson public
|
||
- sans signatures
|
||
- sans clés
|
||
|
||
2) Publication `MsgSignature`
|
||
- une ou plusieurs signatures (selon validateurs)
|
||
- attachées au hash
|
||
|
||
3) Publication `MsgCle`
|
||
- clés / matériels DH nécessaires au déchiffrement
|
||
- attachés au hash
|
||
|
||
## Récupération côté client
|
||
|
||
1) GET `MsgChiffre` (pull périodique, par fenêtre)
|
||
2) Déduplication par hash
|
||
3) GET `MsgCle` (si candidat déchiffrable)
|
||
4) Déchiffrement, parsing, recalcul hash canonique
|
||
5) GET `MsgSignature`
|
||
6) Vérification secp256k1 + validateurs
|
||
7) Mise à jour graphe local
|
||
|
||
## Conditions de login (rappel)
|
||
|
||
Pour se logguer, il faut :
|
||
- cibler un `service_uuid`,
|
||
- trouver l’ActionLogin du membre,
|
||
- satisfaire les validateurs de l’action login,
|
||
- fournir les signatures attendues des pairs requis,
|
||
- publier preuve (message → signatures → clés),
|
||
- permettre au service de vérifier la conformité contrat/signature sans serveur central.
|