Enterprise édition
Listes de confiance — Référence approfondie
En un coup d’œil
Section intitulée « En un coup d’œil »Cette page est la référence approfondie de la surface des listes de confiance dans NextPDF Enterprise. Cette surface, ce sont les douze classes publiques de l’espace de noms NextPDF\Enterprise\Security\Tsl. NextPDF\Enterprise\Security\Tsl\TslPolicyEnforcer est le point d’entrée orchestré : il ne renvoie un TslDocument que lorsque la récupération HTTP, la vérification XMLDSig, l’analyse structurelle et la barrière de péremption nextUpdate réussissent toutes. TslTrustAnchorProvider::buildBundle() dérive ensuite un paquet d’ancres de confiance à partir des services CA/QC actifs, en réaffirmant la fraîcheur à un instant fourni par l’appelant avant toute extraction d’ancre. Chaque échec lève une exception typée ; aucune étape ne se dégrade silencieusement. Le pipeline prend en charge la vérification des listes de confiance des États membres de l’UE et des ancres de confiance issues d’une LOTL (List of Trusted Lists) lorsqu’elles sont fournies par l’appelant ; la découverte automatique de la LOTL, l’interrogation périodique et le traitement des pivots sont hors périmètre.
Disponibilité et licence
Section intitulée « Disponibilité et licence »Cette capacité est livrée dans NextPDF Enterprise (nextpdf/enterprise) et s’active avec une enveloppe de licence de palier Enterprise. Un déploiement dépourvu de ce droit ne charge pas les classes de la capacité. Comparer les éditions et obtenir une licence.
Surface de l’API publique
Section intitulée « Surface de l’API publique »| Symbole | Paramètres | Comportement par défaut | Renvoie | Lève ou échoue avec | Notes |
|---|---|---|---|---|---|
TslPolicyEnforcer | TslFetcher $fetcher, TslSignatureVerifier $verifier, TslXmlParser $parser | Combine récupération, vérification de signature, analyse et barrière de péremption en un seul point d’entrée | — | Propage les exceptions du pipeline ci-dessous | final ; en échec fermé par construction |
TslPolicyEnforcer::fetchAndVerify | string $url | Récupère une TSL, puis exécute verifyXml() sur les octets | TslDocument | TslFetchException, NetworkPolicyViolation, TslSignatureException, TslParseException | Ne renvoie que lorsque les quatre étapes réussissent |
TslPolicyEnforcer::verifyXml | string $xml | Vérifie la signature, analyse et rejette une liste périmée | TslDocument | TslSignatureException, TslParseException | La péremption est évaluée par rapport à l’heure système actuelle |
TslFetcher | ClientInterface $httpClient, RequestFactoryInterface $requestFactory, ?CacheInterface $cache = null, int $defaultTtlSeconds = 3600, int $maxBytes = 16_777_216, NetworkPolicy $networkPolicy = NetworkPolicy::ONLINE | Récupération TSL/LOTL en HTTPS uniquement avec cache basé sur ETag | — | — | final ; la garde SSRF bloque les hôtes privés, de bouclage, lien-local et de métadonnées, avec atténuation du DNS-rebinding |
TslFetcher::fetch | string $url | GET avec revalidation If-None-Match ; met en cache le corps et l’ETag sous le TTL configuré | string (octets XML bruts) | TslFetchException, NetworkPolicyViolation | Lit au plus $maxBytes octets ; sous STRICT_OFFLINE, seul un corps en cache est servi |
TslSignatureVerifier | array $trustAnchorsPem, int $clockTolerance = 0 | Vérificateur XMLDSig épinglé aux ancres de confiance configurées | — | InvalidArgumentException lorsque la liste d’ancres est vide | final ; listes d’autorisation dans ALLOWED_SIG_ALG et ALLOWED_DIGEST_ALG |
TslSignatureVerifier::verify | string $xml | Vérifie la signature XMLDSig enveloppée en échec fermé | string (PEM du certificat signataire) | TslSignatureException avec un code de raison lisible par machine | Les certificats de KeyInfo ne sont jamais dignes de confiance à eux seuls ; le signataire doit chaîner jusqu’à une ancre configurée |
TslXmlParser::parse | string $xml | Analyse structurelle en un TslDocument ; indifférent à la signature | TslDocument | TslParseException | Rejette tout DOCTYPE en échec fermé avant l’analyse ; charge avec LIBXML_NONET ; les appelants doivent vérifier avant de faire confiance au résultat |
TslTrustAnchorProvider::buildBundle | TslDocument $tsl, DateTimeImmutable $now | Affirme d’abord la fraîcheur, puis collecte les certificats des services CA/QC actifs | EnterpriseCaTrustAnchorBundle | TslParseException | La barrière de fraîcheur précède toute extraction d’ancre ; un ensemble de résultats vide lève une exception |
TslDocument | Huit propriétés readonly promues (voir le bloc du constructeur) | Objet-valeur immuable de la TSL analysée | — | — | final readonly ; annoté @api dans la source |
TslDocument::isStale | DateTimeImmutable $now | Compare nextUpdate à $now après une analyse UTC en échec fermé | bool | TslParseException | Requiert un désignateur Z explicite ou un décalage numérique |
TslDocument::assertFresh | DateTimeImmutable $now | Lève une exception lorsque la liste est périmée ou que nextUpdate est inanalysable | void | TslParseException | La barrière de fraîcheur à la frontière du consommateur |
TslDocument::servicesOfType | string $serviceTypeIdentifier | Filtre les services par URI de type de service ETSI | list<TspService> | Ne lève pas | — |
TslDocument::activeServices | — | Renvoie uniquement les services en statut « granted » | list<TspService> | Ne lève pas | « Granted » signifie TspService::STATUS_GRANTED |
TspService | Huit propriétés readonly promues | Une entrée de service de confiance dans une TSL | — | — | final readonly ; constantes pour le statut et les URI de type de service |
TspService::isGranted | — | Égalité de statut avec l’URI « granted » | bool | Ne lève pas | — |
TspService::isQualifiedCa | — | Égalité de type avec l’URI CA/QC | bool | Ne lève pas | — |
TspServiceQualifier | string $qualifierUri, string $criteriaListAssert = 'all', array $policyOidConditions = [], array $keyUsageConditions = [] | Un qualificateur de service ETSI avec critères optionnels | — | — | final readonly ; constantes FOR_ESIG, FOR_ESEAL, FOR_WSA, QSCD_STATEMENT, NO_QSCD |
EnterpriseCaTrustAnchorBundle | array $anchorsPem, string $bundleVersion, string $bundleSha256 | Paquet à ancres épinglées ; valide le condensé fourni par rapport aux ancres fournies à la construction | — | InvalidArgumentException | À obtenir via buildBundle() ; ne pas construire à la main ; implémente TrustAnchorStoreInterface |
EnterpriseCaTrustAnchorBundle::containsFingerprint | string $anchorDerSha256Hex | Appartenance d’une ancre par SHA-256 hexadécimal sur le corps DER | bool | Ne lève pas | — |
EnterpriseCaTrustAnchorBundle::computeBundleSha256 | array $anchorsPem | SHA-256 canonique sur la concaténation PEM normalisée en sauts de ligne | string | Ne lève pas | static |
TslFetchException | — | Signale l’échec d’une récupération de TSL | — | — | final ; étend RuntimeException |
TslParseException | — | Signale un échec structurel ou de fraîcheur | — | — | final ; étend RuntimeException |
TslSignatureException | string $reason, string $message | Signale un échec de vérification XMLDSig avec un code de raison | — | — | final ; $reason readonly public (voir les codes de raison ci-dessous) |
TslPolicyEnforcer
public function fetchAndVerify(string $url): TslDocumentpublic function verifyXml(string $xml): TslDocumentTslFetcher
public function __construct( private readonly ClientInterface $httpClient, private readonly RequestFactoryInterface $requestFactory, private readonly ?CacheInterface $cache = null, private readonly int $defaultTtlSeconds = 3600, private readonly int $maxBytes = 16_777_216, private readonly NetworkPolicy $networkPolicy = NetworkPolicy::ONLINE,) {}
public function fetch(string $url): stringTslSignatureVerifier
public function __construct(private readonly array $trustAnchorsPem, private readonly int $clockTolerance = 0)
public function verify(string $xml): stringTslXmlParser
public function parse(string $xml): TslDocumentTslTrustAnchorProvider
public function buildBundle(TslDocument $tsl, DateTimeImmutable $now): EnterpriseCaTrustAnchorBundleTslDocument
public function __construct( public string $schemeTerritory, public string $schemeOperatorName, public string $tslType, public int $sequenceNumber, public string $issueDateTime, public string $nextUpdate, public array $tspServices, public string $rawXmlSha256,) {}
public function isStale(DateTimeImmutable $now): boolpublic function assertFresh(DateTimeImmutable $now): voidpublic function servicesOfType(string $serviceTypeIdentifier): arraypublic function activeServices(): arrayTspService
public function __construct(public string $tspName, public string $serviceName, public string $serviceTypeIdentifier, public string $serviceStatus, public string $statusStartingTime, public string $serviceCertificatePem, public array $qualifiers, public array $additionalServiceInformation) {}
public function isGranted(): boolpublic function isQualifiedCa(): boolTspServiceQualifier
public function __construct(public string $qualifierUri, public string $criteriaListAssert = 'all', public array $policyOidConditions = [], public array $keyUsageConditions = []) {}EnterpriseCaTrustAnchorBundle
public function __construct(public array $anchorsPem, public string $bundleVersion, public string $bundleSha256)
public function containsFingerprint(string $anchorDerSha256Hex): boolpublic static function computeBundleSha256(array $anchorsPem): stringTslSignatureException
public function __construct(public readonly string $reason, string $message)Codes de raison de TslSignatureException : missing_signature, untrusted_signer, invalid_signature, digest_mismatch, unsupported_algorithm, unsupported_transform, expired_anchor.
Contrat de comportement
Section intitulée « Contrat de comportement »- L’ordre du pipeline est fixe : récupération, vérification XMLDSig, analyse structurelle, barrière de péremption.
TslPolicyEnforcerne renvoie unTslDocumentque lorsque les quatre réussissent. Une liste de confiance est signée par son opérateur de schéma afin que les parties utilisatrices puissent en vérifier l’authenticité et l’intégrité — ETSI TS 119 612 §5.7.1. TslXmlParserest indifférent à la signature par conception. Les appelants doivent vérifier la signature avant de faire confiance à un quelconque champ analysé.TslPolicyEnforcer::verifyXml()impose cet ordre.- L’invariant de fraîcheur est imposé à chaque frontière de consommateur. Une liste dont le
nextUpdateest dépassé est expirée et refusée — ETSI TS 119 612 §5.3.15.verifyXml()filtre par rapport à l’heure système actuelle ;TslDocument::assertFresh()etbuildBundle()filtrent par rapport à un instant fourni par l’appelant. - L’analyse de fraîcheur est en échec fermé. Les champs date-heure sont des valeurs ISO 8601 UTC avec un désignateur explicite — ETSI TS 119 612 §5.1.3. Un
nextUpdatesansZexplicite ni décalage numérique lèveTslParseException; la valeur n’est jamais réinterprétée dans le fuseau horaire local du serveur. buildBundle()appelleassertFresh($now)avant d’extraire toute ancre, puis n’admet que les services à la fois « granted » et CA/QC. « Granted » et « withdrawn » sont les URI de statut des services qualifiés — ETSI TS 119 612 §5.5.4. CA/QC est l’URI de type de service de l’AC qualifiée — ETSI TS 119 612 §5.5.1.1.- La version du paquet est dérivée du territoire du schéma et du numéro de séquence de la TSL. Le numéro de séquence est monotone d’une publication à l’autre — ETSI TS 119 612 §5.3.2. Le condensé du paquet est un SHA-256 canonique sur les PEM des ancres, et
containsFingerprint()répond à l’appartenance par SHA-256 du DER. - Le vérificateur ne fait confiance qu’aux ancres configurées. Les certificats trouvés dans
KeyInfoservent de feuille signataire et d’intermédiaires candidats ; la chaîne doit atteindre une ancre configurée en une profondeur maximale de 8, chaque maillon doit être temporellement valide, et un certificat émetteur doit porterbasicConstraintscA=TRUE(pluskeyCertSignlorsquekeyUsageest présent). - Le profil de vérification est une liste d’autorisation : RSA ou ECDSA avec SHA-256, SHA-384 ou SHA-512 ; méthodes de condensé SHA-256, SHA-384 ou SHA-512 ; canonicalisation exclusive uniquement ; et exactement la paire de transformations « signature enveloppée » plus C14N exclusive sur la
ds:Referencecouvrant la liste. Tout le reste échoue avecunsupported_algorithmouunsupported_transform. TslFetcherrefuse les URL non-HTTPS et applique une garde SSRF avant toute sortie. SousNetworkPolicy::STRICT_OFFLINE, il sert un corps précédemment mis en cache ou lèveNetworkPolicyViolation; aucune requête sortante n’est jamais émise.
Cas limites et modes de défaillance
Section intitulée « Cas limites et modes de défaillance »- Liste périmée. Une
TslParseExceptionissue deverifyXml(),assertFresh()oubuildBundle()signifie que la source de confiance est inutilisable. Traite-la comme un échec de rafraîchissement opérationnel, pas comme un verdict de signature. nextUpdatenon canonique. Une valeur sansZexplicite ni décalage numérique lève une exception au lieu d’être analysée de manière laxiste. ETSI TS 119 612 §5.1.3 impose la forme UTCZ; la barrière accepte aussi un décalage numérique explicite et rejette tout le reste.- Dérive au moment de l’utilisation.
verifyXml()filtre au moment de la vérification ; un document conservé en mémoire au-delà de sonnextUpdateéchoue toujours à la barrière ultérieurebuildBundle($tsl, $now). - Configuration d’ancres vide.
TslSignatureVerifierrefuse la construction avec une liste d’ancres vide (InvalidArgumentException). - Aucun service utilisable. Une liste fraîche sans service CA/QC « granted » lève
TslParseExceptiondepuisbuildBundle(); un paquet vide n’est jamais produit. - Posture hors ligne.
STRICT_OFFLINEsans corps en cache lèveNetworkPolicyViolation. La recherche dans le cache précède la vérification de la politique, si bien qu’une liste en cache maintient la validation en environnement isolé opérationnelle. - Réponse surdimensionnée ou vide.
fetch()lit au plus$maxBytesoctets (16 Mio par défaut) ; une liste tronquée échoue ensuite à la vérification du condensé en aval. Un corps vide lèveTslFetchException. - DOCTYPE dans le XML. Tout DOCTYPE est rejeté avant que libxml ne construise une table d’entités, et de nouveau après le chargement. Cela ferme les classes d’entrée XXE et d’expansion d’entités (billion-laughs).
- Signatures multiples. Seule la
ds:Signatureenveloppée vérifiée est retirée avant le calcul du condensé ; les signatures voisines et les contre-signatures sont préservées. Des références XAdES supplémentaires sont autorisées, mais exactement uneds:Referencedoit couvrir la racine du document. - Matériel de chaîne expiré. Un signataire, un intermédiaire ou une ancre expiré ou pas encore valide échoue avec la raison
expired_anchor.clockToleranceélargit symétriquement la fenêtre d’acceptation et vaut0par défaut.
Comportement en mode FIPS
Section intitulée « Comportement en mode FIPS »La liste d’autorisation du vérificateur est fixée à RSA et ECDSA avec la famille SHA-2 ; SHA-1 et MD5 sont structurellement exclus. L’arithmétique de signature s’exécute dans la cryptographie logicielle embarquée (phpseclib). NextPDF ne formule aucune revendication de validation FIPS 140-3 pour cette arithmétique. Le profil de politique cryptographique FIPS 140-3 d’Enterprise est documenté avec le module de sécurité ; il contraint la sélection d’algorithmes et ne modifie ni les structures des listes de confiance ni le comportement en échec fermé de ce module.
Conformité
Section intitulée « Conformité »| Revendication | Norme | Clause |
|---|---|---|
| Une liste de confiance dont la « Next update » est dépassée est écartée comme expirée. | ETSI TS 119 612 | §5.3.15 |
Les champs date-heure sont des chaînes ISO 8601 en UTC avec le désignateur Z. | ETSI TS 119 612 | §5.1.3 |
| L’opérateur de schéma signe la liste de confiance pour l’authenticité et l’intégrité. | ETSI TS 119 612 | §5.7.1 |
| Le statut d’un service qualifié est l’URI de statut « granted » ou « withdrawn ». | ETSI TS 119 612 | §5.5.4 |
Une AC qualifiée est identifiée par l’URI de type de service Svctype/CA/QC. | ETSI TS 119 612 | §5.5.1.1 |
| Le numéro de séquence de la TSL commence à 1 et s’incrémente à chaque publication. | ETSI TS 119 612 | §5.3.2 |
Toutes les clauses sont paraphrasées ; NextPDF ne reproduit pas le texte normatif. NextPDF ne formule aucune revendication de conformité ETSI TS 119 612 ni aucune revendication de certification eIDAS. Consommer une liste de confiance ne rend « qualifiés » ni une signature, ni un certificat, ni une sortie NextPDF ; la qualification relève du prestataire de services de confiance sous la supervision d’un État membre, et l’effet juridique est en dehors de ce module. Les contraintes du modèle de traitement XMLDSig (transformation « signature enveloppée », canonicalisation exclusive, référence couvrant la racine) sont documentées à partir du profil de vérification du produit ; la spécification W3C XML Signature est en dehors de l’ensemble de preuves cité. Ce module décide seulement si une liste est acceptable comme entrée de confiance ; la validation de chemin de certification par rapport aux ancres résultantes relève de la couche de validation des certificats.
Notes de développement
Section intitulée « Notes de développement »- Les dépendances sont des interfaces PSR : un client PSR-18, une fabrique de requêtes PSR-17 et un cache PSR-16 optionnel. Injecte des doublures en mémoire dans les tests ; aucune étape n’exige un accès réseau réel, hormis un
fetch()à froid. - Épingle l’ancre supérieure hors bande. Pour les listes des États membres, l’ancre LOTL autorise les signataires de listes ; le vérificateur n’amorce jamais la confiance depuis le contenu de
KeyInfo. - L’interrogation périodique en arrière-plan, le traitement des LOTL pivots et l’authentification par TLS mutuel ou par proxy sont hors du périmètre du récupérateur dans cette version. Planifie le rafraîchissement en externe et re-récupère avant chaque
nextUpdate. - Passe l’instant de validation, pas l’instant de construction, à
buildBundle(). Reconstruis le paquet après chaque rafraîchissement ; ne mets jamais un paquet en cache au-delà dunextUpdatede la liste source. bundleVersiona la forme observabletsl-<territory>-seq<sequenceNumber>;rawXmlSha256surTslDocumentprend en charge les enregistrements de preuve et la détection de rejeu.- Les entrées de service malformées sont analysées avec des valeurs de remplacement défensives ; une identité numérique malformée qui atteint la construction du paquet échoue en fermé avec
InvalidArgumentException. - Les classes portent des annotations source de paquet
@since 1.10.0(TslFetchException:3.2.0).TslDocument,TspServiceetTspServiceQualifiersont annotés@apidans la source.
Voir aussi
Section intitulée « Voir aussi »- Niveaux de garantie eIDAS — la page de capacité qui associe les preuves des listes de confiance aux niveaux de garantie.
- Conteneurs ASiC — un consommateur de
TslTrustAnchorProvider::buildBundle()pour la liaison de confiance des conteneurs. - Vérification de signature — le côté vérification AdES/PAdES qui consomme les ancres de confiance.
- Sécurité — Référence approfondie — la surface de sécurité Enterprise combinée.
- Signature — Référence approfondie — le producteur long terme PAdES B-LT et B-LTA.
Frontière de publication
Section intitulée « Frontière de publication »Cette page ne documente que le comportement observable de l’extérieur et la surface de l’API publique prise en charge. Les chemins d’espaces de noms internes, les classes auxiliaires, les tables de mécanismes, les noms de fichiers de runbook et les préfixes de tickets sont hors périmètre.