Aller au contenu

PD-38 — Calcul de l'empreinte probatoire SHA3-256 sur documents chiffrés


📚 Navigation User Story | Document | | | ---------- | -- | | 📋 **Spécification** | *(ce document)* | | 🛠️ [Plan d'implémentation](PD-38-plan.md) | | | ✅ [Critères d'acceptation](PD-38-acceptability.md) | | | 📝 [Retour d'expérience](PD-38-rex.md) | | [← Retour à crypto-proof](../PD-189-epic.md) · [↑ Index User Story](index.md)

Références

  • EPIC : CRYPTO-PROOF (PD-189)
  • JIRA : PD-38
  • Repo(s) concernés : backend

Objectif

Implémenter le calcul systématique d'une empreinte cryptographique probatoire basée sur l'algorithme SHA3-256, appliquée exclusivement aux documents chiffrés, afin de garantir leur intégrité, leur non-altération et leur opposabilité juridique dans le temps.

Cette empreinte constitue la base de toute la chaîne probatoire (signature HSM, horodatage TSA, ancrage blockchain, preuves composites).

Description fonctionnelle

Lors du dépôt d'un document dans ProbatioVault, le système doit calculer une empreinte cryptographique à partir du fichier chiffré transmis par le client.

Cette empreinte permet :

  • de prouver l'intégrité du document sans jamais en révéler le contenu ;
  • de vérifier qu'aucune modification n'a été apportée au fichier ;
  • de servir d'entrée aux mécanismes probatoires avancés (Merkle tree, signature, horodatage, blockchain).

Le calcul de l'empreinte ne doit à aucun moment nécessiter le déchiffrement du document, garantissant ainsi le respect strict du modèle zero-knowledge.

Périmètre

Inclus

  • Calcul d'une empreinte SHA3-256 à partir du fichier chiffré.
  • Caractère déterministe du calcul (même fichier → même empreinte).
  • Association de l'empreinte au document dès l'upload.
  • Stockage de l'empreinte dans la base de données.
  • Restitution de l'empreinte via l'API pour vérification ultérieure.
  • Support de fichiers de taille variable, y compris volumineux.
  • Tests fonctionnels et techniques validant la conformité cryptographique.

Exclu

  • Calcul de hash sur des documents en clair.
  • Mécanismes de signature cryptographique.
  • Horodatage TSA.
  • Construction d'arbres de Merkle.
  • Ancrage blockchain.
  • Vérification client-side de l'empreinte.

Contraintes

  • Sécurité
  • Le hash est calculé exclusivement sur le fichier chiffré.
  • Aucune donnée en clair ne doit être accessible au service.
  • Aucune fuite de l'empreinte ne doit apparaître dans les logs.
  • Toute tentative de hash sur un fichier vide ou invalide doit être rejetée.

  • Conformité cryptographique

  • Utilisation exclusive de l'algorithme SHA3-256 (NIST FIPS 202).
  • Taille de sortie fixe de 256 bits.
  • Résistance aux collisions conforme à l'état de l'art.
  • Compatibilité avec les exigences NF Z42-013 et ISO 14641.

  • Performance

  • Le calcul doit être compatible avec des volumes importants.
  • Le traitement ne doit pas provoquer de surcharge mémoire.
  • Le calcul doit rester compatible avec un usage en production.

  • Qualité

  • Couverture de tests élevée sur le service de calcul.
  • Absence de régression sur le flux d'upload documentaire.
  • Conformité aux règles de qualité et de sécurité du projet.

Hypothèses

  • Les documents sont toujours chiffrés côté client avant transmission.
  • Le stockage du document chiffré est opérationnel.
  • Le schéma de base de données permet l'ajout d'une empreinte probatoire.
  • Les mécanismes probatoires ultérieurs consomment cette empreinte comme entrée de confiance.
  • Les exigences légales imposent un hash indépendant du contenu en clair.

Spécifications techniques

Implémentation

Élément Valeur
Bibliothèque js-sha3 (ou noble-hashes)
Algorithme SHA3-256 (Keccak)
Output 64 caractères hexadécimaux (256 bits)
Colonne DB file_hash VARCHAR(64) UNIQUE
Streaming Supporté pour fichiers volumineux

Stockage base de données

-- Colonne dans vault_secure.documents
file_hash VARCHAR(64) NOT NULL UNIQUE
-- Contrainte : CHECK (file_hash ~ '^[a-f0-9]{64}$')

Exemple d'utilisation

import { sha3_256 } from 'js-sha3';

// Hash d'un buffer
const hash = sha3_256(encryptedFileBuffer);
// Résultat : "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"

// Version streaming pour gros fichiers
const hasher = sha3_256.create();
for await (const chunk of fileStream) {
  hasher.update(chunk);
}
const hashStreaming = hasher.hex();

Diagrammes

Séquence — Calcul et persistance de l'empreinte probatoire

Ce diagramme couvre le flux nominal d'upload avec calcul SHA3-256 sur le ciphertext, stockage en base et restitution.

Les invariants référencés : - Hash sur ciphertext uniquement : le backend ne déchiffre jamais le document (zero-knowledge). - Fichier vide = rejet : toute donnée vide ou invalide est rejetée avant calcul. - Unicité hash par utilisateur : contrainte UNIQUE en base. - Hash jamais en clair dans les logs : aucune empreinte n'apparait dans les traces applicatives.

sequenceDiagram
    participant Client
    participant API as DocumentController
    participant DSS as DocumentSecureService
    participant S3 as OVH S3 (WORM)
    participant HS as HashService
    participant DB as PostgreSQL

    Client->>+API: POST /documents (ciphertext)
    API->>+DSS: create(dto, file)

    Note over DSS: Validation : fichier non vide<br/>(rejet BadRequest si vide/invalide)

    DSS->>+S3: putObject(ciphertext)
    S3-->>-DSS: objectKey

    DSS->>+S3: getObject(objectKey)
    S3-->>-DSS: ciphertext stream

    DSS->>+HS: hashDocumentStream(stream)
    Note over HS: SHA3-256 (FIPS 202)<br/>Streaming par chunks<br/>Sortie : 64 chars hex

    alt Stream vide
        HS-->>DSS: BadRequestException
        DSS-->>API: 400 Bad Request
        API-->>Client: 400 Bad Request
    else Stream valide
        HS-->>-DSS: fileHash (64 hex)
    end

    DSS->>+DB: INSERT document (fileHash)
    Note over DB: UNIQUE constraint sur file_hash<br/>CHECK (file_hash ~ '^[a-f0-9]{64}$')

    alt Hash dupliqué
        DB-->>DSS: ConflictException
        DSS-->>API: 409 Conflict
        API-->>Client: 409 Conflict
    else Insertion OK
        DB-->>-DSS: document entity
    end

    DSS-->>-API: document (avec fileHash)
    API-->>-Client: 201 Created (document)

Séquence — Vérification d'intégrité

Ce diagramme couvre le flux de vérification a posteriori de l'empreinte probatoire d'un document stocké.

sequenceDiagram
    participant Client
    participant API as DocumentController
    participant DSS as DocumentSecureService
    participant S3 as OVH S3 (WORM)
    participant HS as HashService
    participant DB as PostgreSQL

    Client->>+API: GET /documents/:id/verify
    API->>+DSS: verifyIntegrity(documentId)

    DSS->>+DB: findOne(documentId)
    DB-->>-DSS: document (fileHash stocké)

    DSS->>+S3: getObject(objectKey)
    S3-->>-DSS: ciphertext stream

    DSS->>+HS: hashDocumentStream(stream)
    HS-->>-DSS: computedHash

    DSS->>DSS: verify(computedHash, storedHash)
    Note over DSS: Comparaison constant-time<br/>(timingSafeEqual)

    alt Hash identique
        DSS-->>API: { integrity: true }
        API-->>-Client: 200 OK — Intégrité confirmée
    else Hash différent
        DSS-->>API: { integrity: false }
        API-->>Client: 200 OK — Intégrité compromise
    end

États — Cycle de vie de l'empreinte probatoire

L'empreinte traverse trois états principaux liés au document. Une fois calculée et persistée, elle devient l'entrée de confiance pour les mécanismes probatoires avancés (signature HSM, TSA, Merkle, blockchain).

stateDiagram-v2
    [*] --> UPLOADED : Client envoie ciphertext
    UPLOADED --> HASHING : Backend récupère le fichier S3
    HASHING --> HASHED : SHA3-256 calculé + persisté en DB
    HASHING --> REJECTED : Fichier vide / stream invalide

    HASHED --> VERIFIED : Vérification intégrité OK
    HASHED --> COMPROMISED : Hash recalculé ≠ hash stocké

    VERIFIED --> HASHED : (état stable)

    HASHED --> SIGNED : Entrée signature HSM (PD-37)
    HASHED --> TIMESTAMPED : Entrée horodatage TSA (PD-39)
    HASHED --> ANCHORED : Entrée Merkle tree (PD-54)

    REJECTED --> [*]

    note right of HASHED
        Invariants :
        - Hash sur ciphertext uniquement
        - Unicité par utilisateur (UNIQUE DB)
        - 64 chars hex (FIPS 202)
        - Jamais exposé dans les logs
    end note

Liens documentaires

  • Architecture :
  • Architecture TechLead — Garanties probatoires
  • EPIC :
  • CRYPTO-PROOF (PD-189)
  • Sécurité & conformité :
  • Spécifications Techniques ProbatioVault v2.1
  • NF Z42-013
  • ISO 14641
  • NIST FIPS 202 (SHA-3)