PD-264 — Expression de besoin¶
1. Contexte¶
ProbatioVault utilise l'horodatage qualifié RFC 3161 pour ancrer dans le temps les preuves numériques scellées. La vérification formelle (TLA+, Alloy, Z, Prolog) de la conformité RFC 3161 a été réalisée et donne un résultat de 17/18 OK. Le seul point en échec concerne l'absence du mécanisme nonce dans la requête TimeStampReq et la validation de la réponse TimeStampResp.
Le nonce est exigé par la RFC 3161 : - Section 2.2 : Le client PEUT inclure un nonce dans la requête pour détecter les attaques par rejeu. - Section 2.4.2 : Si un nonce est présent dans la requête, il DOIT être vérifié dans la réponse. - Section 4.6 : Le nonce protège contre les attaques où un attaquant tenterait de réutiliser un jeton d'horodatage ancien.
L'infrastructure existe (colonne nonce dans la table timestamp_tokens, paramètre nonce? dans l'interface IQtsaClientService), mais le mécanisme n'est ni activé, ni implémenté, ni testé.
Dépendance : PD-55 (worker ancrage blockchain) — les entités TSA, le module NestJS, et le processeur Bull existent (status: DONE).
2. Objectifs principaux¶
- OBJ-01 : Garantir la protection anti-rejeu de chaque jeton d'horodatage RFC 3161 produit par ProbatioVault, conformément à la norme.
- OBJ-02 : Atteindre un score de conformité Prolog RFC 3161 de 18/18 (actuellement 17/18).
- OBJ-03 : Assurer l'interopérabilité des jetons d'horodatage produits avec les outils standards (
openssl ts -verify). - OBJ-04 : Permettre la détection et le rejet de toute réponse TSA dont le nonce ne correspond pas à la requête émise.
- OBJ-05 : Vérifier que le format ASN.1/DER des jetons d'horodatage est conforme à la RFC 3161 section 2.4.2.
3. Non-objectifs (exclusions explicites)¶
- NON-01 : L'implémentation du client QTSA complet (appel HTTP vers une TSA externe) — ce qui n'est pas encore implémenté dans le
BatchTimestampProcessorreste hors périmètre si ce n'est pas directement lié au nonce. - NON-02 : La rotation ou la révocation des certificats TSA.
- NON-03 : L'intégration d'une nouvelle TSA externe (on travaille avec le framework existant).
- NON-04 : La modification de la politique de rétention des jetons (10 ans, défini par PD-55).
4. Contraintes¶
Juridiques et réglementaires¶
- C-01 : Le nonce DOIT être conforme à la RFC 3161 (minimum 64 bits recommandé, ProbatioVault vise 128 bits pour marge de sécurité).
- C-02 : Le jeton d'horodatage DOIT rester parsable et vérifiable par
openssl ts -verify(interopérabilité). - C-03 : La vérification formelle Prolog DOIT passer à 18/18 après implémentation.
Techniques (héritées de PD-55)¶
- C-04 : La table
timestamp_tokensest protégée par un trigger d'immutabilité — aucune mise à jour possible après insertion. - C-05 : Le nonce DOIT être généré avec un CSPRNG (crypto-random), jamais
Math.random(). - C-06 : La comparaison nonce requête/réponse DOIT être en temps constant pour éviter les attaques par canal auxiliaire.
Techniques (arbitrages PO)¶
- C-09 : Le nonce DOIT être stocké en BYTEA (binaire brut, 16 octets) et non en VARCHAR — évite les ambiguïtés de normalisation (leading zeros). La colonne existante
VARCHAR(64)devra être migrée versBYTEA(16). - C-10 : Un index unique sur la colonne
nonceest requis — protection anti-rejeu applicative complémentaire (défense en profondeur). - C-11 : Le nonce fait partie de l'événement probatoire initial — sa validation DOIT être complète AVANT toute insertion en DB, journal append-only ou inclusion Merkle.
- C-12 : L'implémentation DOIT être dans le module
tsa/principal (couche protocolaire). Le moduledual-validation/consomme l'abstraction, il ne porte pas la logique nonce.
Stratégie de test (arbitrage PO)¶
- C-13 : CI standard (rapide, déterministe) — mock TSA conforme RFC 3161 pour tests unitaires ASN.1/DER et validation structure + signature.
- C-14 : Pipeline probatoire nightly — appel vers une TSA qualifiée réelle, vérification
openssl ts -verify, archivage du token TSA produit comme artefact probatoire.
Organisationnelles¶
- C-07 : Priorité haute — seule non-conformité bloquante identifiée par la vérification formelle.
- C-08 : Sprint PD Sprint 9 (2026-02-20 au 2026-03-16).
5. Scénarios d'échec et résultats inacceptables¶
- FAIL-01 : Un jeton d'horodatage est produit sans nonce dans un environnement de production — la protection anti-rejeu est absente et la conformité RFC 3161 n'est pas atteinte.
- FAIL-02 : Un nonce mismatch entre requête et réponse n'est pas détecté — un attaquant pourrait substituer une réponse TSA légitime par une ancienne.
- FAIL-03 : Le nonce est généré mais non persisté — la traçabilité est rompue et l'audit est incomplet.
- FAIL-04 : Le format DER du jeton d'horodatage produit n'est pas interopérable —
openssl ts -verifyéchoue. - FAIL-05 : Le pipeline CI régresse (Sonar QG FAILED, couverture < 80%) suite aux modifications.
- FAIL-06 : La TSA renvoie un token valide mais sans nonce — si ce cas n'est pas rejeté, la conformité stricte RFC 3161 n'est pas atteinte (certaines TSA acceptent des requêtes sans nonce, mais ProbatioVault DOIT exiger la présence du nonce dans la réponse).
6. Tensions et conflits — Arbitrages PO¶
Les 3 tensions identifiées ont été arbitrées :
- TENSION-01 (résolue) : Le nonce est implémenté dans le module
tsa/principal (couche protocolaire RFC 3161). Le worker BullMQ d'ancrage périodique (BatchTimestampProcessor) consomme cette couche. Le cycle de vie exact est : request -> nonce -> tsa_token -> merkle aggregation -> blockchain anchor. La clarification du service cible est un pré-requis de la spécification. - TENSION-02 (résolue) : Stockage en BYTEA (binaire brut, 16 octets). Le nonce est encodé en
INTEGERASN.1 pour le protocole, stocké en binaire en DB, comparé en binaire. Pas de VARCHAR — évite les ambiguïtés de leading zeros. - TENSION-03 (confirmée comme invariant) : Le trigger d'immutabilité est maintenu. Conséquence : la validation complète du nonce (génération, envoi, réception, comparaison) DOIT être achevée AVANT toute écriture. Le nonce fait partie de l'événement probatoire initial.
7. Invariant de sécurité formel¶
INV-SEC-NONCE : Pour toute réponse TSA acceptée : - nonce_response == nonce_request (comparaison binaire, temps constant) - nonce_request n'existe pas dans NonceStore (unicité — index unique DB) - nonce_response est présent (non null) dans la réponse
Cet invariant rend la conformité testable et vérifiable formellement.
8. Questions ouvertes (restantes)¶
Toutes les questions initiales ont reçu des réponses du PO. Aucune question ouverte bloquante ne subsiste.