Sécurité / Signature : CMS, horodatage RFC 3161, LTV, confiance
Cette page décrit la surface de signature livrée avec NextPDF Core : production d’une signature CMS, application d’un horodatage RFC 3161, validation d’une chaîne de certificats selon RFC 5280 et vérification de la révocation via OCSP et CRL. Elle se place au niveau comportemental. Les classes d’implémentation de Core sont internes : le code de production consomme le contrat SignerInterface, et non les types concrets NextPDF\Security\Signature. Le succès de la vérification d’une signature produite dépend du vérificateur et des ancres de confiance avec lesquelles il est configuré. Ce résultat échappe au contrôle du producteur ; cette page le précise partout où cela compte.
Installation
Section intitulée « Installation »composer require nextpdf/core:^3Vue d’ensemble conceptuelle
Section intitulée « Vue d’ensemble conceptuelle »Core construit une structure CMS SignedData à partir de la plage d’octets, puis la stocke, encodée en DER, dans l’entrée Contents du dictionnaire de signature — ISO 32000-2 §12.8.1. La structure porte des attributs signés de SignerInfo — notamment content-type et message-digest — RFC 5652 §5.3. Un vérificateur recalcule l’empreinte du contenu et la compare à l’attribut message-digest. Les valeurs doivent correspondre pour que la signature soit valide — RFC 5652 §5.4. Le SignerInfo porte aussi l’identifiant de l’algorithme d’empreinte et le bloc d’attributs signés — RFC 5652 §5. Core signe via phpseclib3 pour les chemins logiciels qu’il livre : RSA, RSASSA-PSS, ECDSA et Ed25519.
Un horodatage RFC 3161 est un échange requête-réponse avec une autorité d’horodatage qui renvoie une structure TSTInfo — RFC 3161 §2.4.1. Chaque jeton porte un serialNumber unique pour la TSA émettrice — RFC 3161 §2.4.2 — et un genTime exprimé en UTC, correspondant à l’instant où le jeton a été créé — RFC 3161 §2.4.2.
La validation de la confiance repose sur deux vérifications. La validation du chemin remonte du certificat du signataire jusqu’à une ancre de confiance, en vérifiant les contraintes de base et les entrées de construction du chemin — RFC 5280 §6.1. La vérification de révocation interroge un répondeur OCSP ou lit une CRL : une réponse OCSP indique good, revoked ou unknown — RFC 6960 §2.2 — et les champs thisUpdate et nextUpdate de la réponse bornent la fraîcheur de ce statut — RFC 6960 §4.2. Les ancres de confiance et la politique de fraîcheur de la révocation sont fournies par l’appelant. Le moteur valide uniquement à partir de ce qui lui est fourni et n’inclut aucune liste de confiance intégrée.
Surface d’API
Section intitulée « Surface d’API »| Type | Nature | Rôle | Stabilité | Depuis |
|---|---|---|---|---|
SignerInterface | interface (NextPDF\Contracts) | Contrat de signature dont dépendent les appelants | stable | 1.0.0 |
SignatureLevel | enum | Sélection du niveau PAdES et détection de disponibilité | stable | 1.0.0 |
Rfc5280PathValidator | interface | Point d’entrée de la validation du chemin de certification (validate(...)) | stable (figé en 3.1.0) | 3.1.0 |
RevocationStatus | enum | Résultat OCSP / CRL : good, revoked, unknown | stable | 3.1.0 |
CaTrustAnchorBundle | type | Ensemble d’ancres de confiance fourni par l’appelant | stable | 3.1.0 |
TstInfo | type | Champs d’horodatage RFC 3161 analysés | stable | 3.2.0 |
SignerInterface::sign() renvoie un SignatureResult dont toHex() fournit la chaîne hexadécimale /Contents et dont la propriété cmsSignedData contient les octets DER bruts. Les classes concrètes NextPDF\Security\Signature qui implémentent ces comportements sont internes (stability: internal dans le manifeste du module) ; elles ne font pas partie de l’API publique et peuvent changer sans incrément de version majeure. Appuie-toi sur les contrats et les enums ci-dessus.
Exemple de code — Démarrage rapide
Section intitulée « Exemple de code — Démarrage rapide »<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\SignerInterface;
/** * Produce the CMS SignedData hex for a PDF /Contents field. * * @param SignerInterface $signer A Core or Premium signer. * @param string $byteRange The PDF byte range to sign. * * @return string Hex-encoded CMS SignedData. */function sign(SignerInterface $signer, string $byteRange): string{ return $signer->sign($byteRange)->toHex();}L’appelant ne dépend que du contrat. Un signataire logiciel Core et un signataire HSM Premium satisfont tous deux SignerInterface, donc ce code reste inchangé d’une édition à l’autre.
Exemple de code — Production
Section intitulée « Exemple de code — Production »<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\SignerInterface;use NextPDF\Contracts\TimestampProviderInterface;use NextPDF\Exception\NextPdfException;use Psr\Log\LoggerInterface;
final readonly class TimestampedSigner{ public function __construct( private SignerInterface $signer, private TimestampProviderInterface $timestamps, private LoggerInterface $logger, ) {}
/** * Sign a byte range, then timestamp the CMS structure. * * The timestamp's trust still depends on the verifier accepting the * Time-Stamping Authority; this method only produces the structure. * * @param string $byteRange The PDF byte range to sign. * * @return array{cms: string, tst: string} */ public function sign(string $byteRange): array { try { $signature = $this->signer->sign($byteRange); $token = $this->timestamps->getTimestamp($signature->cmsSignedData);
return ['cms' => $signature->toHex(), 'tst' => $token]; } catch (NextPdfException $e) { $this->logger->error('Signing failed', ['error' => $e->getMessage()]);
throw $e; } }}Le fournisseur d’horodatage est injecté afin qu’un déploiement puisse épingler sa propre autorité d’horodatage. Le bloc catch journalise l’exception puis la relance. Il n’avale jamais l’échec, ce qui maintient le chemin de signature en fail-closed.
Cas limites & pièges
Section intitulée « Cas limites & pièges »- Une signature produite n’est pas une signature vérifiée. La validation du chemin et la révocation s’exécutent côté vérificateur, avec les ancres de confiance de ce vérificateur. Le producteur ne peut pas affirmer le résultat.
- L’empreinte de la plage d’octets exclut la valeur de signature. Une empreinte qui couvrirait les octets
Contentsne peut pas être vérifiée — ISO 32000-2 §12.8.1. - Le statut de révocation est borné par une fenêtre de fraîcheur. Une réponse OCSP n’est à jour que dans la limite de son intervalle
thisUpdate/nextUpdate— RFC 6960 §4.2. Une réponse périmée ne remplace pas une vérification fraîche au moment de la validation. - Le moteur n’inclut aucune liste de confiance intégrée.
CaTrustAnchorBundleest fourni par l’appelant ; un ensemble vide signifie qu’aucune chaîne ne se valide, par conception. - OCSP
unknownn’est pasgood. Traiteunknowncomme une absence de statut déterminé, pas comme une réussite implicite — RFC 6960 §2.2. - La garde des clés HSM, la signature différée et dans le cloud, et le producteur PAdES B-LT / B-LTA ne sont pas dans Core. Choisir ces chemins dans la distribution Core échoue en fail-closed avec un message nommant le composant Enterprise manquant.
Performances
Section intitulée « Performances »Une signature logicielle prend quelques millisecondes, typiquement à un seul chiffre. Un horodatage ajoute un aller-retour réseau vers la TSA. La validation du chemin est locale une fois les certificats en mémoire ; la révocation ajoute une récupération OCSP ou CRL par certificat de la chaîne. Le budget de 1500 ms en temps réel couvre une seule signature horodatée avec une TSA distante sur une connexion à chaud. La vérification de révocation auprès d’un point de terminaison lent le dépasse et a sa place en dehors du chemin de requête. Le profil de reproductibilité est structural : un horodatage intègre l’instant de signature, donc deux exécutions diffèrent par les octets d’horodatage tandis que la structure du document reste identique.
Notes de sécurité
Section intitulée « Notes de sécurité »C’est la principale frontière cryptographique du moteur, donc le modèle de menace est explicite. La plage d’octets est calculée par le moteur et n’est jamais acceptée de l’appelant. Le chemin de signature est fail-closed : un échec de primitive ou une capacité manquante lève une exception typée et ne se rabat jamais silencieusement sur un algorithme plus faible. À un niveau exigeant un horodatage (B-T, B-LT, B-LTA), une autorité d’horodatage qui renvoie un jeton vide constitue une défaillance terminale : la signature est refusée, et non émise dans un état rétrogradé, silencieusement non horodaté, à moins qu’un gestionnaire de défaillance ne soit câblé pour autoriser une dégradation documentée. Par conception, la confiance est contrôlée par l’appelant — les ancres et la politique de révocation sont des entrées, pas des valeurs par défaut du moteur — parce qu’un producteur qui affirmerait sa propre confiance affirmerait un fait que seul le vérificateur peut établir. La confiance dans l’horodatage se ramène à la confiance dans l’autorité d’horodatage, qui est injectable pour qu’un déploiement puisse épingler la sienne. Cette page est marquée export_control_class: legal-review-required parce qu’elle concerne la signature cryptographique ; chaque source normative est paraphrasée et aucune n’est reproduite, conformément à l’hygiène de citation.
Conformité
Section intitulée « Conformité »| Affirmation | Standard | Clause | Preuve |
|---|---|---|---|
La signature CMS est stockée encodée en DER dans l’entrée Contents du dictionnaire de signature. | ISO 32000-2 | §12.8.1 | |
| SignerInfo porte les attributs signés content-type et message-digest. | RFC 5652 | §5.3 | |
| Le vérificateur recalcule l’empreinte du contenu et la compare à l’attribut message-digest. | RFC 5652 | §5.4 | |
| Un jeton d’horodatage est produit par un horodateur RFC 3161 (une TSA) et porte un serialNumber unique et un genTime en UTC. | RFC 3161 | §2.4.1, §2.4.2 | ,, |
| La validation du chemin de certification vérifie les contraintes de base et les entrées du chemin, du signataire jusqu’à une ancre de confiance. | RFC 5280 | §6.1 | , |
| OCSP rapporte certStatus sous la forme good, revoked ou unknown, avec une fraîcheur bornée par thisUpdate / nextUpdate. | RFC 6960 | §2.2, §4.2 | , |
Toutes les clauses sont paraphrasées. NextPDF ne reproduit pas le texte normatif. Consulte les standards publiés pour la formulation faisant autorité.
Contexte commercial
Section intitulée « Contexte commercial »Core fournit le signataire logiciel CMS (RSA, RSASSA-PSS, ECDSA, Ed25519), la consommation d’horodatages RFC 3161, la validation de chemin RFC 5280 et la vérification de révocation OCSP / CRL. La garde des clés HSM et PKCS#11, la signature différée et dans le cloud, le producteur PAdES B-LT et B-LTA, ainsi que le profil de politique cryptographique FIPS 140-3 sont livrés dans les éditions Pro et Enterprise. Core résout ces éléments à l’exécution via le contrat, donc le moteur open-source ne porte aucune dépendance commerciale et l’API ne change pas lors de la mise à niveau.
Voir aussi
Section intitulée « Voir aussi »- Correspondance des niveaux PAdES — Core versus Premium sur B-B, B-T, B-LT, B-LTA.
- Contracts / Signing — le SPI
SignerInterfaceet les niveaux de stabilité. - Sécurité — le chiffrement et la surface de signature plus large.
- Conformité — l’application de profils qui va de pair avec l’archivage signé.
- CMS · RFC 3161 timestamp · LTV · DSS · VRI · HSM — termes du glossaire.