Enterprise édition
Liaison de confiance ASiC
Un conteneur ASiC regroupe des fichiers signés avec les signatures qui les protègent. La vraie question n’est pas « la signature est-elle correcte ? » mais « qui se porte garant du signataire ? ». NextPDF\Enterprise\Security\Asic\AsicTrustBinder répond précisément à cette question. Tu lui fournis le certificat de signature issu de la signature du conteneur, une liste de confiance et un instant de validation. Il répond par un AsicTrustBindingResult : un verdict de confiance ou de défiance, la version du lot d’ancres qu’il a retenue pour se prononcer et des motifs lisibles par une machine. Chaque rejet nomme sa cause, si bien que la preuve d’audit s’écrit d’elle-même.
Une limite est délibérée et mérite d’être posée d’emblée. Cette API n’analyse pas les conteneurs ASiC. Ton outillage ouvre le conteneur et en extrait le certificat de signature ; NextPDF est responsable de la décision de confiance.
Disponibilité et licence
Section intitulée « Disponibilité et licence »Cette fonctionnalité est fournie dans NextPDF Enterprise (nextpdf/enterprise) et s’active avec une enveloppe de licence de niveau Enterprise. Un déploiement dépourvu de ce droit ne charge pas les classes de la fonctionnalité. Comparer les éditions et obtenir une licence.
Installation
Section intitulée « Installation »composer require nextpdf/enterpriseL’activation requiert ton enveloppe de licence Enterprise. Voir Installer et s’authentifier. Les classes présentées sur cette page se trouvent sous NextPDF\Enterprise\Security\Asic et NextPDF\Enterprise\Security\Tsl.
Vue d’ensemble conceptuelle
Section intitulée « Vue d’ensemble conceptuelle »ASiC (Associated Signature Containers, ETSI EN 319 162-1) regroupe des fichiers de données et des signatures dans une même archive. Un conteneur ASiC baseline n’embarque que des signatures CAdES ou XAdES baseline. Une signature CAdES baseline transporte son certificat de signature dans SignedData.certificates, de sorte qu’un vérificateur est censé l’extraire de la signature du conteneur lorsque la signature est bien formée et prise en charge par l’outillage de conteneur. Ce certificat extrait constitue l’entrée de cette API.
La source de confiance est une liste de confiance (TSL) ETSI TS 119 612 : un document XML signé qui énumère les prestataires de services de confiance et leurs certificats de service. NextPDF\Enterprise\Security\Tsl\TslTrustAnchorProvider convertit un TslDocument analysé en un lot d’ancres. Seuls les services à la fois en statut granted et de type de service CA/QC alimentent l’ensemble d’ancres. Le lot porte une chaîne de version dérivée du numéro de séquence et du territoire de la TSL, ainsi qu’un condensé d’intégrité SHA-256.
Deux contrôles à sûreté intégrée s’exécutent avant toute comparaison d’ancres :
- Fraîcheur de la TSL. Une liste de confiance dont l’instant
NextUpdateest dépassé doit être écartée comme expirée.AsicTrustBinder::verify()vérifie la fraîcheur à l’instant de validation fourni avant de dériver la moindre ancre. Une liste périmée, ou une valeurNextUpdatesans désignateur UTC explicite, lèveTslParseException. - Période de validité du signataire. La validation de chemin RFC 5280 exige que la période de validité du certificat inclue l’instant de validation. Une signature cryptographiquement intacte dont le certificat était expiré, ou pas encore valide, à cet instant est rejetée avec un code de motif précis.
Ce n’est qu’ensuite que le lieur teste le certificat de signature face à chaque ancre. Une correspondance donne trusted: true avec le motif anchor_signature_match. L’absence de correspondance donne trusted: false avec le motif no_anchor_chain.
Pourquoi ce fonctionnement
Section intitulée « Pourquoi ce fonctionnement »La décision de conception porteuse est une séparation stricte entre la mécanique du conteneur et la décision de confiance, cette dernière étant contrainte d’être explicite sur le temps. Les formats de conteneur varient (ASiC-S, ASiC-E, charges utiles CAdES ou XAdES), mais la question de confiance forme un noyau invariant : ce certificat se rattache-t-il à une ancre issue d’une liste de confiance fraîche à un instant donné ? Garder ce noyau exempt d’analyse ZIP et XML le maintient assez réduit pour être testé de façon exhaustive et pour échouer en sûreté à chaque contrôle. Le même raisonnement interdit un now implicite par défaut : l’instant de validation change le verdict, l’appelant doit donc en assumer la responsabilité. La fraîcheur est vérifiée au sein même du chemin de dérivation des ancres, et non dans un collaborateur optionnel, de sorte qu’aucun chemin producteur ne peut la contourner.
Contexte de conception : Comment une signature numérique prouve qui a signé.
Surface de l’API
Section intitulée « Surface de l’API »AsicTrustBinder
Section intitulée « AsicTrustBinder »Le constructeur prend le fournisseur d’ancres qui transforme les listes de confiance en lots d’ancres.
public function __construct( private readonly TslTrustAnchorProvider $anchorProvider,) {}Le point d’entrée principal vérifie un certificat de signataire face à une liste de confiance :
public function verify( string $signerCertPem, TslDocument $tsl, DateTimeInterface $validationTime,): AsicTrustBindingResult$signerCertPem— chaîne PEM non vide : le certificat de signature issu de la signature ASiC.$tsl— la liste de confiance analysée et authentifiée.$validationTime— l’instant que la période de validité du certificat de signataire doit inclure. Il n’y a pas de valeur par défaut.
Lève ou échoue avec : NextPDF\Enterprise\Security\Tsl\TslParseException lorsque la TSL est périmée (NextUpdate dépassé), lorsque NextUpdate n’est pas une valeur UTC canonique, ou lorsque la liste ne contient aucun service CA/QC actif. Les signataires non fiables ne lèvent pas d’exception ; ils renvoient un résultat avec trusted: false et un code de motif.
Pour les traitements par lots, vérifie face à un lot pré-construit :
public function verifyAgainstBundle( string $signerCertPem, EnterpriseCaTrustAnchorBundle $bundle, DateTimeInterface $validationTime,): AsicTrustBindingResultLève ou échoue avec : aucune exception qui lui soit propre ; chaque issue est un AsicTrustBindingResult. Obtiens le lot via TslTrustAnchorProvider::buildBundle() — ne le construis pas à la main.
TslTrustAnchorProvider
Section intitulée « TslTrustAnchorProvider »public function buildBundle(TslDocument $tsl, DateTimeImmutable $now): EnterpriseCaTrustAnchorBundleLève ou échoue avec : TslParseException si la TSL est périmée, si son NextUpdate n’est pas une valeur UTC canonique, ou si elle n’a aucun service CA/QC actif.
AsicTrustBindingResult
Section intitulée « AsicTrustBindingResult »public function __construct( public bool $trusted, public string $anchorBundleVersion, public array $reasons,) {}$reasons est une list<non-empty-string> de codes lisibles par une machine. $anchorBundleVersion consigne l’ensemble d’ancres utilisé, sous la forme tsl-<territory>-seq<N> (par exemple tsl-eu-seq42).
| Code de motif | Signification |
|---|---|
anchor_signature_match | Le certificat de signataire se vérifie face à une ancre dérivée de la TSL. De confiance. |
no_anchor_chain | Aucune ancre du lot ne vérifie le certificat de signataire. Non fiable. |
signer_cert_expired | L’instant de validation tombe après le notAfter du certificat. Non fiable. |
signer_cert_not_yet_valid | L’instant de validation tombe avant le notBefore du certificat. Non fiable. |
cannot_parse_signer_cert | Le PEM fourni ne s’analyse pas comme un certificat X.509. Non fiable. |
Exemple de code — Démarrage rapide
Section intitulée « Exemple de code — Démarrage rapide »Ton outillage de conteneur a déjà extrait le certificat de signature. Lie-le à une liste de confiance d’un État membre que tu as récupérée et authentifiée (voir Listes de confiance).
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Security\Asic\AsicTrustBinder;use NextPDF\Enterprise\Security\Tsl\TslParseException;use NextPDF\Enterprise\Security\Tsl\TslTrustAnchorProvider;use NextPDF\Enterprise\Security\Tsl\TslXmlParser;
// Extracted by YOUR tooling from META-INF/signature.p7s or signatures.xml.$signerCertPem = (string) file_get_contents(__DIR__ . '/asic-signer.pem');
// A trusted list you have already fetched and authenticated.$tslXml = (string) file_get_contents(__DIR__ . '/member-state-tsl.xml');
$binder = new AsicTrustBinder(new TslTrustAnchorProvider());
try { $tsl = (new TslXmlParser())->parse($tslXml);
$result = $binder->verify( signerCertPem: $signerCertPem, tsl: $tsl, validationTime: new DateTimeImmutable('2026-07-03T12:00:00Z'), );} catch (TslParseException $e) { // Fail closed: stale TSL, malformed NextUpdate, or no active CA/QC services. fwrite(STDERR, 'Trusted list rejected: ' . $e->getMessage() . PHP_EOL); exit(1);}
echo $result->trusted ? "TRUSTED\n" : "NOT TRUSTED\n";echo 'Anchors: ' . $result->anchorBundleVersion . "\n";echo 'Reasons: ' . implode(', ', $result->reasons) . "\n";Sortie attendue pour un signataire émis par un service CA/QC répertorié :
TRUSTEDAnchors: tsl-eu-seq42Reasons: anchor_signature_matchExemple de code — Production
Section intitulée « Exemple de code — Production »Dérive le lot d’ancres une fois par liste de confiance, puis vérifie de nombreux signataires de conteneur face à lui. Une seule TSL périmée ou inutilisable fait échouer tout le lot en sûreté ; les problèmes de signataire individuels remontent par conteneur.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Security\Asic\AsicTrustBinder;use NextPDF\Enterprise\Security\Asic\AsicTrustBindingResult;use NextPDF\Enterprise\Security\Tsl\TslDocument;use NextPDF\Enterprise\Security\Tsl\TslParseException;use NextPDF\Enterprise\Security\Tsl\TslTrustAnchorProvider;use NextPDF\Enterprise\Security\Tsl\TslXmlParser;
/** * @param array<string, non-empty-string> $signerPemsByContainer PEM per container path. * @return array<string, AsicTrustBindingResult> * @throws TslParseException When no anchor set can be derived from the TSL. */function bindBatch( TslDocument $tsl, array $signerPemsByContainer, DateTimeImmutable $validationTime,): array { $provider = new TslTrustAnchorProvider();
// Derive the anchor set ONCE; a throw here means the trusted list itself // is unusable at this validation time. $bundle = $provider->buildBundle($tsl, $validationTime);
$binder = new AsicTrustBinder($provider);
$results = []; foreach ($signerPemsByContainer as $container => $signerPem) { $results[$container] = $binder->verifyAgainstBundle( signerCertPem: $signerPem, bundle: $bundle, validationTime: $validationTime, ); }
return $results;}
$tsl = (new TslXmlParser())->parse( (string) file_get_contents(__DIR__ . '/member-state-tsl.xml'),);
$signerPems = [ 'invoice-2026-06.asice' => (string) file_get_contents(__DIR__ . '/signer-a.pem'), 'tender-2019.asice' => (string) file_get_contents(__DIR__ . '/signer-b.pem'),];
try { $results = bindBatch( tsl: $tsl, signerPemsByContainer: $signerPems, validationTime: new DateTimeImmutable('now', new DateTimeZone('UTC')), );} catch (TslParseException $e) { // Fail closed for the WHOLE batch: no trustworthy anchor set exists. fwrite(STDERR, 'Anchor derivation failed: ' . $e->getMessage() . PHP_EOL); exit(1);}
foreach ($results as $container => $result) { printf( "%s => %s (%s; anchors %s)\n", $container, $result->trusted ? 'trusted' : 'rejected', implode(',', $result->reasons), $result->anchorBundleVersion, );}Sortie attendue lorsqu’un certificat de signataire a expiré :
invoice-2026-06.asice => trusted (anchor_signature_match; anchors tsl-eu-seq42)tender-2019.asice => rejected (signer_cert_expired; anchors tsl-eu-seq42)Cas limites et pièges
Section intitulée « Cas limites et pièges »- L’instant de validation est obligatoire et décisif. Il n’y a pas de
nowimplicite par défaut. Une signature qui se vérifiait en 2019 signalesigner_cert_expiredlorsque tu valides à un instant de 2026 postérieur aunotAfter. Pour du matériel historique, passe l’instant que tes preuves étayent (par exemple un instant de preuve d’existence), et non l’horloge murale. - Une TSL périmée lève une exception ; ce n’est pas un verdict de « défiance ». Une
TslParseExceptionissue deverify()oubuildBundle()signifie que la source de confiance est inutilisable. Traite-la comme une défaillance opérationnelle : rafraîchis la liste, ne la consigne pas comme un rejet de signataire. - Les ancres sont testées comme émetteurs directs. Chaque ancre est essayée comme le certificat qui a signé le certificat de signataire. Les TSL des États membres de l’UE répertorient les certificats de service CA/QC émetteurs, de sorte que les certificats qualifiés d’entité finale correspondent généralement de façon directe. Un signataire émis par une AC intermédiaire qui n’est pas elle-même un service CA/QC actif répertorié donne
no_anchor_chain. - La dérivation des ancres filtre sévèrement. Les services retirés, ou de tout type autre que CA/QC, ne deviennent jamais des ancres. Une liste dont l’ensemble CA/QC actif est vide lève une exception plutôt que de produire un lot vide.
NextUpdatedoit être en UTC canonique. Une valeur sans désignateurZexplicite ou décalage numérique est rejetée en sûreté intégrée, jamais réinterprétée dans le fuseau horaire local du serveur.- Une entrée mal formée se dégrade avec précision. Un PEM qui ne s’analyse pas renvoie
cannot_parse_signer_cert; un certificat pas encore valide se distingue d’un certificat expiré. - Consigne
anchorBundleVersion. Il nomme l’ensemble d’ancres exact (tsl-<territory>-seq<N>) derrière chaque verdict, ce que réclamera un auditeur.
Notes de sécurité
Section intitulée « Notes de sécurité »- Sûreté intégrée par construction. La fraîcheur est vérifiée avant toute dérivation d’ancre. Le contrôle de validité du signataire s’exécute avant toute comparaison d’ancres. Le matériel de confiance inutilisable lève une exception ; les signataires douteux sont rejetés avec des motifs. Aucun chemin ne se dégrade en une réussite silencieuse.
- La liaison de confiance est une couche, pas l’ensemble de la validation. Cette API ne vérifie pas la valeur de signature CAdES sur le contenu du conteneur, ne contrôle pas la révocation (aucune consultation CRL ou OCSP) et n’authentifie pas le document TSL lui-même. Authentifie d’abord la liste via le pipeline de listes de confiance (voir Listes de confiance), vérifie la signature de façon cryptographique avec ton outillage de signature, et ajoute le contrôle de révocation selon ta politique.
- Choisis l’instant de validation délibérément. Le verdict est fonction de l’instant que tu passes. Dérive-le d’une preuve digne de confiance (un horodatage qualifié, un enregistrement d’archives), et non d’une horloge influençable par un attaquant.
- Les sorties de preuve sont déterministes.
trusted,anchorBundleVersionetreasonssont des valeurs stables et lisibles par une machine, adaptées à des journaux d’audit signés.
Conformité
Section intitulée « Conformité »AsicTrustBinder prend en charge des flux alignés sur ETSI EN 319 162-1 (conteneurs ASiC baseline), ETSI EN 319 122-1 (signatures CAdES baseline) et ETSI TS 119 612 (listes de confiance), et applique le contrôle de période de validité RFC 5280 à l’instant de validation fourni.
La prise en charge n’est pas la conformité, et la conformité n’est pas la certification. NextPDF met en œuvre les contrôles décrits sur cette page ; il n’a été certifié conforme à ces normes par aucun organisme, et l’utilisation de cette API ne rend pas à elle seule ta sortie « qualifiée » ou juridiquement effective au titre d’eIDAS ou de tout autre régime. NextPDF ne détient aucune certification et n’en confère aucune. Déterminer si un processus de validation complet satisfait une exigence légale ou d’achat donnée revient à tes évaluateurs.
Comportement en mode FIPS
Section intitulée « Comportement en mode FIPS »La liaison de confiance effectue des contrôles de signature de certificat X.509 en cours de processus ; elle n’est pas acheminée par le garde d’exécution en mode FIPS d’Enterprise, et l’activation du mode FIPS ne change pas son comportement. Ce n’est pas un service cryptographique validé FIPS, et aucune certification FIPS 140 n’est revendiquée. Les déploiements soumis à des obligations FIPS devraient cadrer cette API en conséquence et consulter Politique cryptographique FIPS 140-2/3.
Contrat de comportement
Section intitulée « Contrat de comportement »verify()ne dérive des ancres que d’une TSL fraîche à l’instant de validation fourni ; une liste périmée ou mal formée lèveTslParseExceptionavant qu’aucune ancre n’existe.- Les ancres dérivent exclusivement des services TSL en statut granted et de type de service CA/QC ; un ensemble actif vide lève une exception.
- La période de validité du certificat de signataire doit inclure l’instant de validation ; les manquements renvoient
signer_cert_expiredousigner_cert_not_yet_valid. - Chaque issue est un
AsicTrustBindingResultportanttrusted,anchorBundleVersionet au moins un code de motif ; il n’existe aucun verdict sans motif. - Les signataires non fiables sont renvoyés, jamais levés ; le matériel de confiance inutilisable est levé, jamais renvoyé comme verdict.
- L’analyse de conteneur n’a jamais lieu au sein de cette API ; les entrées sont le PEM extrait, la liste de confiance et l’instant de validation.
Repli sur Core
Section intitulée « Repli sur Core »NextPDF Core valide les signatures PDF (CMS/PAdES) face aux ancres de confiance que tu épingles explicitement via son contrat CaTrustAnchorBundle — voir Sécurité de Core. Core n’a aucune ingestion de liste de confiance (TSL) ni de liaison de confiance propre à ASiC. Avec Core seul, tu peux maintenir ton propre ensemble d’ancres pour la validation des signatures PDF ; dériver des ancres d’une liste de confiance ETSI TS 119 612 et y lier les signataires de conteneur ASiC requiert NextPDF Enterprise.
Périmètre de publication
Section intitulée « Périmètre de publication »Cette page ne documente que le comportement observable de l’extérieur et la surface d’API publique prise en charge. Les chemins de namespace internes, les classes utilitaires, les tables de mécanismes, les noms de fichiers de runbook et les préfixes de ticket sont hors périmètre.
Voir aussi
Section intitulée « Voir aussi »- Listes de confiance — récupérer, authentifier et analyser la TSL qui alimente le fournisseur d’ancres.
- Vérification de signature — la surface de vérification Enterprise pour les signatures PDF.
- Politique cryptographique FIPS 140-2/3 — la posture du mode FIPS d’Enterprise.
- Comment une signature numérique prouve qui a signé — contexte fondamental.
- Validation à long terme — pourquoi l’instant de validation et les preuves conservées importent.