Aller au contenu

PD-37 — Service de signature HSM des journaux d'audit probatoires


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

Références

  • EPIC : PD-189 — CRYPTO
  • JIRA : PD-37
  • Repo(s) concernés : backend

Objectif

Mettre en place un service centralisé de signature cryptographique des journaux d'audit métier, exécuté exclusivement dans un HSM, afin de garantir la non-répudiation, l'intégrité et l'auditabilité des événements probatoires de ProbatioVault.

Ce service constitue le socle de confiance des journaux d'audit, conformes aux exigences NF Z42-013 et ISO 14641.

Description fonctionnelle

Chaque événement métier significatif (upload, accès, partage, rotation de clé, suppression, etc.) doit être enregistré dans un journal d'audit append-only.

Pour chaque entrée d'audit : - une représentation canonique déterministe de l'événement est produite ; - une empreinte cryptographique est calculée ; - cette empreinte est signée via une clé privée détenue exclusivement dans un HSM certifié ; - l'ensemble (événement canonique, empreinte, signature, horodatage) est stocké de manière immuable.

La signature doit pouvoir être vérifiée de façon indépendante, sans dépendre du backend ProbatioVault, garantissant ainsi une preuve opposable dans le temps.

Périmètre

Inclus

  • Canonicalisation déterministe des entrées d'audit.
  • Calcul d'une empreinte cryptographique de l'entrée canonique.
  • Signature cryptographique de l'empreinte via un HSM.
  • Stockage append-only des journaux d'audit signés.
  • Association de chaque signature à l'identifiant de la clé HSM utilisée.
  • Mise à disposition d'un service centralisé de journalisation utilisable par l'ensemble des modules backend.
  • Vérification cryptographique possible a posteriori.
  • Tests fonctionnels, cryptographiques et de charge.

Exclu

  • Construction de l'arbre de Merkle.
  • Ancrage blockchain.
  • Export de preuve composite.
  • Signature d'enveloppes PRE ou d'autres artefacts.
  • Gestion des clés HSM (création, rotation, révocation).

Contraintes

  • Sécurité
  • Aucune clé privée ne doit quitter le HSM.
  • Le backend ne doit jamais manipuler de clé en clair.
  • Les journaux internes ne doivent contenir aucune donnée sensible liée aux signatures ou aux entrées canoniques.
  • Toute modification a posteriori d'une entrée doit être détectable.

  • Conformité probatoire

  • Les journaux doivent être strictement append-only.
  • Chaque entrée doit être horodatée.
  • La signature doit être vérifiable indépendamment du système.
  • Le mécanisme doit être compatible NF Z42-013 et ISO 14641.

  • Robustesse

  • Aucune entrée partielle ne doit être créée en cas d'erreur HSM.
  • Une indisponibilité temporaire du HSM doit être gérée proprement.
  • Le service doit supporter une volumétrie élevée d'événements.

  • Performance

  • La signature d'une entrée doit rester compatible avec un usage temps réel.
  • Le service ne doit pas devenir un point de contention majeur.

Hypothèses

  • Un HSM compatible PKCS#11 est disponible et correctement configuré.
  • Les événements métier sont définis de manière structurée et sérialisable de façon déterministe.
  • Le stockage PostgreSQL supporte les contraintes d'immutabilité requises.
  • Les mécanismes de Merkle tree et d'ancrage blockchain consommeront ultérieurement ces journaux signés.
  • Les exigences légales imposent une preuve indépendante du backend.

Diagrammes

Séquence — Signature HSM d'une entrée d'audit (flux nominal)

Ce diagramme couvre le pipeline complet de signature probatoire : canonicalisation, hachage, signature HSM et stockage append-only.

Invariants référencés : - Clé privée confinée au HSM : le backend envoie le hash au HSM, jamais de clé en clair. - Canonicalisation déterministe : RFC 8785, garantit un hash reproductible. - Append-only : toute entrée signée est insérée sans possibilité de UPDATE/DELETE. - Aucune donnée sensible dans les logs : ni signature, ni empreinte, ni contenu canonique.

sequenceDiagram
    participant Caller as Module métier
    participant ALS as AuditLogService
    participant ASS as AuditSignatureService
    participant JCS as JsonCanonicalizeService
    participant HS as HashService
    participant HSM as HsmService (PKCS#11)
    participant DB as PostgreSQL (vault_secure)

    Caller->>+ALS: emitAuditEvent(entry)
    ALS->>+ASS: signAuditEntry(entry)

    ASS->>+JCS: canonicalize(entry)
    Note over JCS: RFC 8785 — tri lexicographique,<br/>pas d'espaces, UTF-8 strict
    JCS-->>-ASS: entryCanonical (string)

    ASS->>+HS: hash(entryCanonical)
    Note over HS: SHA3-256 (FIPS 202)<br/>Sortie : 32 bytes
    HS-->>-ASS: entryHash (Buffer)

    ASS->>+HSM: sign(entryHash, keyLabel, ECDSA_P256)
    Note over HSM: Clé privée ECDSA P-256<br/>non-exportable, Sign=true<br/>Label : probatiovault-audit-ecdsa-p256
    HSM-->>-ASS: {signature (DER), keyLabel}

    ASS->>+DB: INSERT audit_log (entryCanonical, entryHash, hsmSignature, hsmKeyId, ...)
    Note over DB: Table append-only<br/>Trigger bloque UPDATE/DELETE
    DB-->>-ASS: saved entity

    ASS-->>-ALS: SignedAuditResult {id, hash, signature, keyId, timestamp}
    ALS-->>-Caller: void (fire-and-forget via queue)

Séquence — Vérification indépendante d'une entrée d'audit

Ce diagramme couvre la vérification a posteriori d'un journal signé, réalisable sans accès au HSM grâce aux clés publiques exportées (cf. E-01 résolu).

Invariants référencés : - Vérification indépendante du backend : la signature est vérifiable avec la clé publique seule. - Détection de tampering : le hash est recalculé depuis l'entrée canonique et comparé. - Preuve opposable : compatible NF Z42-013 et ISO 14641.

sequenceDiagram
    participant V as Vérificateur (externe ou interne)
    participant AVS as AuditVerificationService
    participant DB as PostgreSQL (vault_secure)
    participant HS as HashService

    V->>+AVS: verifyAuditEntry(id)
    AVS->>+DB: SELECT audit_log WHERE id = ?
    DB-->>-AVS: {entryCanonical, entryHash, hsmSignature, hsmKeyId}

    AVS->>+DB: SELECT hsm_public_keys WHERE key_id = hsmKeyId
    DB-->>-AVS: publicKey (PEM)

    AVS->>+HS: hash(entryCanonical)
    Note over HS: SHA3-256 — recalcul<br/>depuis l'entrée canonique
    HS-->>-AVS: recomputedHash

    alt Hash mismatch
        Note over AVS: recomputedHash != entryHash<br/>Entrée altérée
        AVS-->>V: {valid: false, error: "Hash mismatch — entry tampered"}
    else Hash OK
        AVS->>AVS: crypto.verify(null, entryHash, publicKey, hsmSignature)
        Note over AVS: ECDSA raw verify<br/>(pas de createVerify — cf. CKM_ECDSA)

        alt Signature invalide
            AVS-->>V: {valid: false, error: "Signature verification failed"}
        else Signature valide
            AVS-->>-V: {valid: true, keyId, timestamp}
        end
    end

Etats — Cycle de vie d'une entrée d'audit

Ce diagramme modélise les états possibles d'une entrée d'audit depuis sa soumission jusqu'à sa vérification ou son échec définitif.

Invariants référencés : - Pas d'entrée partielle : une entrée en erreur HSM est mise en queue, jamais stockée partiellement. - Robustesse : retry exponentiel (3 tentatives) via BullMQ avant passage en DLQ. - Append-only irréversible : une fois signée et stockée, l'entrée ne peut plus être modifiée.

stateDiagram-v2
    [*] --> QUEUED : Module métier émet un événement

    QUEUED --> SIGNING : BullMQ dépile le job
    SIGNING --> SIGNED : Canonicalisation + Hash + HSM OK
    SIGNING --> RETRY : Erreur HSM (timeout, indisponibilité)

    RETRY --> SIGNING : Tentative N+1 (backoff exponentiel)
    RETRY --> FAILED_DLQ : 3 tentatives épuisées

    SIGNED --> STORED : INSERT append-only (vault_secure.audit_log)
    STORED --> [*]

    FAILED_DLQ --> RETRY : Relance manuelle (endpoint DLQ)
    FAILED_DLQ --> ABANDONED : Abandon explicite (opérateur)

    state STORED {
        [*] --> IMMUTABLE
        IMMUTABLE --> VERIFIED : Vérification indépendante OK
        IMMUTABLE --> TAMPERED : Hash mismatch ou signature invalide
    }

    note right of SIGNED
        Clé privée reste dans le HSM.
        Signature ECDSA P-256 (DER).
    end note

    note right of FAILED_DLQ
        Monitoring Prefect (cron */15).
        Alerte si entrées en DLQ.
    end note

Liens documentaires

  • Architecture :
  • Architecture Probatoire — Journaux et signatures
  • EPIC :
  • PD-189 — CRYPTO
  • Sécurité & conformité :
  • NF Z42-013
  • ISO 14641
  • Spécifications ProbatioVault — Audit & traçabilité
  • PKCS#11 / HSM Guidelines