Salta ai contenuti
getnextpdf.com

Enterprise edizione

Trusted list — Riferimento approfondito

Questa pagina è il riferimento approfondito della superficie trusted-list in NextPDF Enterprise. La superficie è costituita dalle dodici classi pubbliche del namespace NextPDF\Enterprise\Security\Tsl. NextPDF\Enterprise\Security\Tsl\TslPolicyEnforcer è il punto d’ingresso orchestrato: restituisce un TslDocument solo quando fetch HTTP, verifica XMLDSig, parsing strutturale e il gate di obsolescenza su nextUpdate superano tutti la verifica. TslTrustAnchorProvider::buildBundle() deriva quindi un bundle di trust anchor dai servizi CA/QC attivi, riaffermando la freschezza a un istante fornito dal chiamante prima che venga estratto qualsiasi anchor. Ogni fallimento solleva un’eccezione tipizzata; nessuno stadio degrada silenziosamente. La pipeline supporta la verifica delle trusted list degli Stati membri dell’UE e dei trust anchor provenienti da LOTL (List of Trusted Lists) quando forniti dal chiamante; la scoperta automatica del LOTL, il polling e l’elaborazione dei pivot sono fuori ambito.

Questa capacità è inclusa in NextPDF Enterprise (nextpdf/enterprise) e si attiva con un envelope di licenza di tier Enterprise. Un deployment privo di tale entitlement non carica le classi della capacità. Confronta le edizioni e ottieni una licenza.

SimboloParametriComportamento predefinitoRestituisceSolleva o fallisce conNote
TslPolicyEnforcerTslFetcher $fetcher, TslSignatureVerifier $verifier, TslXmlParser $parserCombina fetch, verifica firma, parsing e gate di obsolescenza in un unico punto d’ingressoPropaga le eccezioni della pipeline seguentifinal; fail-closed per costruzione
TslPolicyEnforcer::fetchAndVerifystring $urlEffettua il fetch di una TSL, quindi esegue verifyXml() sui byteTslDocumentTslFetchException, NetworkPolicyViolation, TslSignatureException, TslParseExceptionRestituisce solo quando tutti e quattro gli stadi superano la verifica
TslPolicyEnforcer::verifyXmlstring $xmlVerifica la firma, esegue il parsing e rifiuta una lista obsoletaTslDocumentTslSignatureException, TslParseExceptionL’obsolescenza è valutata rispetto all’ora di sistema corrente
TslFetcherClientInterface $httpClient, RequestFactoryInterface $requestFactory, ?CacheInterface $cache = null, int $defaultTtlSeconds = 3600, int $maxBytes = 16_777_216, NetworkPolicy $networkPolicy = NetworkPolicy::ONLINERecupero TSL/LOTL solo su HTTPS con caching basato su ETagfinal; la guardia SSRF blocca host privati, loopback, link-local e di metadati con mitigazione del DNS rebinding
TslFetcher::fetchstring $urlGET con rivalidazione If-None-Match; mette in cache il body più l’ETag secondo il TTL configuratostring (byte XML grezzi)TslFetchException, NetworkPolicyViolationLegge al massimo $maxBytes byte; sotto STRICT_OFFLINE viene servito solo un body in cache
TslSignatureVerifierarray $trustAnchorsPem, int $clockTolerance = 0Verificatore XMLDSig fissato ai trust anchor configuratiInvalidArgumentException quando la lista di anchor è vuotafinal; allowlist in ALLOWED_SIG_ALG e ALLOWED_DIGEST_ALG
TslSignatureVerifier::verifystring $xmlVerifica la firma XMLDSig enveloped in modalità fail-closedstring (PEM del certificato firmatario)TslSignatureException con un codice di motivo leggibile dalla macchinaI certificati in KeyInfo non sono mai considerati affidabili da soli; il firmatario deve concatenarsi a un anchor configurato
TslXmlParser::parsestring $xmlParsing strutturale in un TslDocument; agnostico rispetto alla firmaTslDocumentTslParseExceptionRifiuta qualsiasi DOCTYPE in modalità fail-closed prima del parsing; carica con LIBXML_NONET; i chiamanti devono verificare prima di considerare affidabile il risultato
TslTrustAnchorProvider::buildBundleTslDocument $tsl, DateTimeImmutable $nowAfferma prima la freschezza, quindi raccoglie i certificati dei servizi CA/QC attiviEnterpriseCaTrustAnchorBundleTslParseExceptionIl gate di freschezza precede qualsiasi estrazione di anchor; un insieme di risultati vuoto solleva un’eccezione
TslDocumentOtto proprietà readonly promosse (vedi il fence del costruttore)Value object immutabile della TSL parsatafinal readonly; @api annotato nel sorgente
TslDocument::isStaleDateTimeImmutable $nowConfronta nextUpdate con $now dopo un parse UTC fail-closedboolTslParseExceptionRichiede un designatore Z esplicito o un offset numerico
TslDocument::assertFreshDateTimeImmutable $nowSolleva un’eccezione quando la lista è obsoleta o nextUpdate non è parsabilevoidTslParseExceptionIl gate di freschezza al confine del consumatore
TslDocument::servicesOfTypestring $serviceTypeIdentifierFiltra i servizi per URI di service-type ETSIlist<TspService>Non solleva eccezioni
TslDocument::activeServicesRestituisce solo i servizi in stato grantedlist<TspService>Non solleva eccezioniGranted significa TspService::STATUS_GRANTED
TspServiceOtto proprietà readonly promosseUna voce di trust-service all’interno di una TSLfinal readonly; costanti per gli URI di stato e di service-type
TspService::isGrantedUguaglianza di stato rispetto all’URI grantedboolNon solleva eccezioni
TspService::isQualifiedCaUguaglianza di tipo rispetto all’URI CA/QCboolNon solleva eccezioni
TspServiceQualifierstring $qualifierUri, string $criteriaListAssert = 'all', array $policyOidConditions = [], array $keyUsageConditions = []Un qualificatore di servizio ETSI con criteri opzionalifinal readonly; costanti FOR_ESIG, FOR_ESEAL, FOR_WSA, QSCD_STATEMENT, NO_QSCD
EnterpriseCaTrustAnchorBundlearray $anchorsPem, string $bundleVersion, string $bundleSha256Bundle di anchor fissati; convalida il digest fornito rispetto agli anchor forniti in fase di costruzioneInvalidArgumentExceptionOttenuto da buildBundle(); non costruire a mano; implementa TrustAnchorStoreInterface
EnterpriseCaTrustAnchorBundle::containsFingerprintstring $anchorDerSha256HexAppartenenza di un anchor tramite SHA-256 esadecimale sul body DERboolNon solleva eccezioni
EnterpriseCaTrustAnchorBundle::computeBundleSha256array $anchorsPemSHA-256 canonico sulla concatenazione PEM con newline normalizzatestringNon solleva eccezionistatic
TslFetchExceptionSegnala un recupero TSL fallitofinal; estende RuntimeException
TslParseExceptionSegnala un fallimento strutturale o di freschezzafinal; estende RuntimeException
TslSignatureExceptionstring $reason, string $messageSegnala un fallimento della verifica XMLDSig con un codice di motivofinal; $reason pubblico readonly (vedi i codici di motivo sotto)

TslPolicyEnforcer

public function fetchAndVerify(string $url): TslDocument
public function verifyXml(string $xml): TslDocument

TslFetcher

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): string

TslSignatureVerifier

public function __construct(private readonly array $trustAnchorsPem, private readonly int $clockTolerance = 0)
public function verify(string $xml): string

TslXmlParser

public function parse(string $xml): TslDocument

TslTrustAnchorProvider

public function buildBundle(TslDocument $tsl, DateTimeImmutable $now): EnterpriseCaTrustAnchorBundle

TslDocument

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): bool
public function assertFresh(DateTimeImmutable $now): void
public function servicesOfType(string $serviceTypeIdentifier): array
public function activeServices(): array

TspService

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(): bool
public function isQualifiedCa(): bool

TspServiceQualifier

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): bool
public static function computeBundleSha256(array $anchorsPem): string

TslSignatureException

public function __construct(public readonly string $reason, string $message)

Codici di motivo di TslSignatureException: missing_signature, untrusted_signer, invalid_signature, digest_mismatch, unsupported_algorithm, unsupported_transform, expired_anchor.

  • L’ordine della pipeline è fisso: fetch, verifica XMLDSig, parsing strutturale, gate di obsolescenza. TslPolicyEnforcer restituisce un TslDocument solo quando tutti e quattro riescono. Una trusted list è firmata dal suo scheme operator così che le relying party possano verificarne autenticità e integrità — ETSI TS 119 612 §5.7.1.
  • TslXmlParser è agnostico rispetto alla firma per progettazione. I chiamanti devono verificare la firma prima di considerare affidabile qualsiasi campo parsato. TslPolicyEnforcer::verifyXml() impone tale ordinamento.
  • L’invariante di freschezza è imposta a ogni confine del consumatore. Una lista il cui nextUpdate è trascorso è scaduta e viene rifiutata — ETSI TS 119 612 §5.3.15. verifyXml() applica il gate rispetto all’ora di sistema corrente; TslDocument::assertFresh() e buildBundle() applicano il gate rispetto a un istante fornito dal chiamante.
  • Il parse di freschezza è fail-closed. I campi data-ora sono valori ISO 8601 in UTC con un designatore esplicito — ETSI TS 119 612 §5.1.3. Un nextUpdate privo di un Z esplicito o di un offset numerico solleva TslParseException; il valore non viene mai reinterpretato nel fuso orario locale del server.
  • buildBundle() chiama assertFresh($now) prima di estrarre qualsiasi anchor, quindi ammette solo i servizi che sono sia granted sia CA/QC. Granted e withdrawn sono gli URI di stato dei servizi qualificati — ETSI TS 119 612 §5.5.4. CA/QC è l’URI di service-type della CA qualificata — ETSI TS 119 612 §5.5.1.1.
  • La versione del bundle è derivata dal territorio dello schema e dal numero di sequenza della TSL. Il numero di sequenza è monotòno tra le release — ETSI TS 119 612 §5.3.2. Il digest del bundle è uno SHA-256 canonico sui PEM degli anchor, e containsFingerprint() risponde sull’appartenenza tramite SHA-256 del DER.
  • Il verificatore considera affidabili solo gli anchor configurati. I certificati trovati in KeyInfo fungono da leaf firmatario e da intermedi candidati; la catena deve raggiungere un anchor configurato entro una profondità di 8, ogni collegamento deve essere temporalmente valido e un certificato emittente deve recare basicConstraints cA=TRUE (più keyCertSign quando keyUsage è presente).
  • Il profilo di verifica è un allowlist: RSA o ECDSA con SHA-256, SHA-384 o SHA-512; metodi di digest SHA-256, SHA-384 o SHA-512; solo canonicalizzazione esclusiva; ed esattamente la coppia di transform enveloped-signature più C14N esclusiva sul ds:Reference che copre la lista. Qualsiasi altra cosa fallisce con unsupported_algorithm o unsupported_transform.
  • TslFetcher rifiuta gli URL non HTTPS e applica una guardia SSRF prima di qualsiasi egress. Sotto NetworkPolicy::STRICT_OFFLINE serve un body precedentemente messo in cache oppure solleva NetworkPolicyViolation; nessuna richiesta in uscita viene mai inviata.
  • Lista obsoleta. Una TslParseException da verifyXml(), assertFresh() o buildBundle() significa che la fonte di trust è inutilizzabile. Trattala come un fallimento operativo di refresh, non come un verdetto sulla firma.
  • nextUpdate non canonico. Un valore privo di un Z esplicito o di un offset numerico solleva un’eccezione invece di essere parsato in modo permissivo. ETSI TS 119 612 §5.1.3 impone la forma UTC Z; il gate accetta anche un offset numerico esplicito e rifiuta tutto il resto.
  • Deriva del momento d’uso. verifyXml() applica il gate al momento della verifica; un documento mantenuto in memoria oltre nextUpdate fallisce comunque il successivo gate di buildBundle($tsl, $now).
  • Configurazione di anchor vuota. TslSignatureVerifier rifiuta la costruzione con una lista di anchor vuota (InvalidArgumentException).
  • Nessun servizio utilizzabile. Una lista fresca senza servizi CA/QC granted solleva una TslParseException da buildBundle(); un bundle vuoto non viene mai prodotto.
  • Postura offline. STRICT_OFFLINE senza un body in cache solleva NetworkPolicyViolation. La ricerca in cache precede il controllo della policy, così una lista in cache mantiene funzionante la validazione air-gapped.
  • Risposta sovradimensionata o vuota. fetch() legge al massimo $maxBytes byte (predefinito 16 MiB); una lista troncata fallisce poi la verifica del digest a valle. Un body vuoto solleva TslFetchException.
  • DOCTYPE nell’XML. Qualsiasi DOCTYPE viene rifiutato prima che libxml costruisca una tabella di entità, e di nuovo dopo il caricamento. Questo chiude le classi di input XXE ed espansione di entità (billion-laughs).
  • Firme multiple. Solo la ds:Signature enveloped verificata viene rimossa prima del calcolo del digest; le firme fratelli e le contro-firme sono preservate. Sono ammessi riferimenti XAdES aggiuntivi, ma esattamente un ds:Reference deve coprire la radice del documento.
  • Materiale di catena scaduto. Un firmatario, un intermedio o un anchor scaduto o non ancora valido fallisce con il motivo expired_anchor. clockTolerance allarga la finestra di accettazione in modo simmetrico e vale 0 per impostazione predefinita.

L’allowlist del verificatore è fissata a RSA ed ECDSA con la famiglia SHA-2; SHA-1 e MD5 sono strutturalmente esclusi. L’aritmetica di firma viene eseguita nella crittografia software inclusa (phpseclib). NextPDF non avanza alcuna rivendicazione di validazione FIPS 140-3 per tale aritmetica. Il profilo di crypto-policy FIPS 140-3 di Enterprise è documentato con il modulo di sicurezza; vincola la selezione degli algoritmi e non modifica le strutture trusted-list né il comportamento fail-closed di questo modulo.

RivendicazioneStandardClausola
Una trusted list il cui Next update è trascorso viene scartata come scaduta.ETSI TS 119 612§5.3.15
I campi data-ora sono stringhe ISO 8601 in UTC con il designatore Z.ETSI TS 119 612§5.1.3
Lo scheme operator firma la trusted list per autenticità e integrità.ETSI TS 119 612§5.7.1
Lo stato dei servizi qualificati è l’URI di stato granted o withdrawn.ETSI TS 119 612§5.5.4
Una CA qualificata è identificata dall’URI di service-type Svctype/CA/QC.ETSI TS 119 612§5.5.1.1
Il numero di sequenza della TSL parte da 1 e si incrementa a ogni release.ETSI TS 119 612§5.3.2

Tutte le clausole sono parafrasate; NextPDF non riproduce il testo normativo. NextPDF non avanza alcuna rivendicazione di conformità a ETSI TS 119 612 né alcuna rivendicazione di certificazione eIDAS. Consumare una trusted list non rende una firma, un certificato o un output NextPDF “qualificato”; la qualificazione appartiene al trust service provider sotto la supervisione dello Stato membro, e l’effetto legale è al di fuori di questo modulo. I vincoli del modello di elaborazione XMLDSig (transform enveloped-signature, canonicalizzazione esclusiva, riferimento che copre la radice) sono documentati a partire dal profilo di verifica del prodotto; la specifica W3C XML Signature è al di fuori dell’insieme di evidenze citate. Questo modulo decide solo se una lista sia accettabile come input di trust; la validazione del percorso di certificazione rispetto agli anchor risultanti appartiene al livello di validazione dei certificati.

  • Le dipendenze sono interfacce PSR: un client PSR-18, una request factory PSR-17 e una cache PSR-16 opzionale. Inietta double in-memory nei test; nessuno stadio richiede accesso di rete reale tranne un fetch() a freddo.
  • Fissa l’anchor superiore out of band. Per le liste degli Stati membri, l’anchor LOTL autorizza i firmatari delle liste; il verificatore non avvia mai la trust a partire dal contenuto di KeyInfo.
  • Il polling in background, l’elaborazione del pivot-LOTL e l’autenticazione mutual-TLS o proxy sono fuori dall’ambito del fetcher in questa versione. Pianifica il refresh esternamente e riesegui il fetch prima di ogni nextUpdate.
  • Passa l’istante di validazione, non l’istante di costruzione, a buildBundle(). Ricostruisci il bundle dopo ogni refresh; non mettere mai in cache un bundle oltre il nextUpdate della lista sorgente.
  • bundleVersion ha la forma osservabile tsl-<territory>-seq<sequenceNumber>; rawXmlSha256 su TslDocument supporta i record di evidenza e il rilevamento del replay.
  • Le voci di servizio malformate vengono parsate con valori placeholder difensivi; un’identità digitale malformata che raggiunge la costruzione del bundle fallisce in modalità fail-closed con InvalidArgumentException.
  • Le classi recano annotazioni sorgente di package @since 1.10.0 (TslFetchException: 3.2.0). TslDocument, TspService e TspServiceQualifier sono annotati @api nel sorgente.

Questa pagina documenta solo il comportamento osservabile dall’esterno e la superficie API pubblica supportata. I percorsi di namespace interni, le classi helper, le tabelle dei meccanismi, i nomi dei file di runbook e i prefissi dei ticket sono fuori ambito.