Enterprise edição
Listas confiáveis — Referência Profunda
Visão geral
Seção intitulada “Visão geral”Esta página é a referência aprofundada da superfície de listas confiáveis no NextPDF Enterprise. A superfície são as doze classes públicas do namespace NextPDF\Enterprise\Security\Tsl. NextPDF\Enterprise\Security\Tsl\TslPolicyEnforcer é o ponto de entrada orquestrado: ele retorna um TslDocument somente quando o fetch HTTP, a verificação XMLDSig, o parse estrutural e o portão de obsolescência nextUpdate passam, todos. TslTrustAnchorProvider::buildBundle() então deriva um pacote de âncoras de confiança a partir dos serviços CA/QC ativos, reafirmando a atualidade em um instante fornecido pelo chamador antes que qualquer âncora seja extraída. Cada falha lança uma exceção tipada; nenhum estágio degrada silenciosamente. O pipeline oferece suporte à verificação de listas confiáveis de Estados-membros da UE e a âncoras de confiança originadas de LOTL (List of Trusted Lists) quando fornecidas pelo chamador; a descoberta automática de LOTL, o polling e o processamento de pivots estão fora do escopo.
Disponibilidade e licenciamento
Seção intitulada “Disponibilidade e licenciamento”Esta capacidade é entregue no NextPDF Enterprise (nextpdf/enterprise) e é ativada com um envelope de licença de nível Enterprise. Uma implantação sem essa habilitação não carrega as classes da capacidade. Compare as edições e obtenha uma licença.
Superfície pública da API
Seção intitulada “Superfície pública da API”| Símbolo | Parâmetros | Comportamento padrão | Retorna | Lança ou falha com | Notas |
|---|---|---|---|---|---|
TslPolicyEnforcer | TslFetcher $fetcher, TslSignatureVerifier $verifier, TslXmlParser $parser | Combina fetch, verificação de assinatura, parse e portão de obsolescência em um único ponto de entrada | — | Propaga as exceções de pipeline abaixo | final; fail-closed por construção |
TslPolicyEnforcer::fetchAndVerify | string $url | Faz o fetch de uma TSL e então executa verifyXml() sobre os bytes | TslDocument | TslFetchException, NetworkPolicyViolation, TslSignatureException, TslParseException | Retorna somente quando os quatro estágios passam |
TslPolicyEnforcer::verifyXml | string $xml | Verifica a assinatura, faz o parse e rejeita uma lista obsoleta | TslDocument | TslSignatureException, TslParseException | A obsolescência é avaliada contra a hora atual do sistema |
TslFetcher | ClientInterface $httpClient, RequestFactoryInterface $requestFactory, ?CacheInterface $cache = null, int $defaultTtlSeconds = 3600, int $maxBytes = 16_777_216, NetworkPolicy $networkPolicy = NetworkPolicy::ONLINE | Recuperação de TSL/LOTL somente por HTTPS com cache baseado em ETag | — | — | final; a proteção contra SSRF bloqueia hosts privados, de loopback, link-local e de metadados com mitigação de DNS-rebinding |
TslFetcher::fetch | string $url | GET com revalidação If-None-Match; faz cache do corpo mais o ETag sob o TTL configurado | string (bytes XML brutos) | TslFetchException, NetworkPolicyViolation | Lê no máximo $maxBytes bytes; sob STRICT_OFFLINE apenas um corpo em cache é servido |
TslSignatureVerifier | array $trustAnchorsPem, int $clockTolerance = 0 | Verificador XMLDSig fixado às âncoras de confiança configuradas | — | InvalidArgumentException quando a lista de âncoras está vazia | final; allowlists em ALLOWED_SIG_ALG e ALLOWED_DIGEST_ALG |
TslSignatureVerifier::verify | string $xml | Verifica a assinatura XMLDSig envelopada de forma fail-closed | string (PEM do certificado do assinante) | TslSignatureException com um código de motivo legível por máquina | Certificados em KeyInfo nunca são confiáveis por si só; o assinante deve encadear até uma âncora configurada |
TslXmlParser::parse | string $xml | Parse estrutural em um TslDocument; agnóstico à assinatura | TslDocument | TslParseException | Rejeita qualquer DOCTYPE de forma fail-closed antes do parse; carrega com LIBXML_NONET; os chamadores devem verificar antes de confiar no resultado |
TslTrustAnchorProvider::buildBundle | TslDocument $tsl, DateTimeImmutable $now | Afirma a atualidade primeiro e então coleta os certificados dos serviços CA/QC ativos | EnterpriseCaTrustAnchorBundle | TslParseException | O portão de atualidade precede qualquer extração de âncora; um conjunto de resultados vazio lança exceção |
TslDocument | Oito propriedades readonly promovidas (veja a cerca do construtor) | Objeto de valor imutável da TSL parseada | — | — | final readonly; anotado na fonte com @api |
TslDocument::isStale | DateTimeImmutable $now | Compara nextUpdate contra $now após um parse UTC fail-closed | bool | TslParseException | Exige um designador Z explícito ou de offset numérico |
TslDocument::assertFresh | DateTimeImmutable $now | Lança exceção quando a lista está obsoleta ou nextUpdate é imparseável | void | TslParseException | O portão de atualidade na fronteira do consumidor |
TslDocument::servicesOfType | string $serviceTypeIdentifier | Filtra serviços pela URI de tipo de serviço da ETSI | list<TspService> | Não lança exceção | — |
TslDocument::activeServices | — | Retorna serviços apenas no status granted | list<TspService> | Não lança exceção | Granted significa TspService::STATUS_GRANTED |
TspService | Oito propriedades readonly promovidas | Uma entrada de serviço de confiança dentro de uma TSL | — | — | final readonly; constantes para status e URIs de tipo de serviço |
TspService::isGranted | — | Igualdade de status contra a URI granted | bool | Não lança exceção | — |
TspService::isQualifiedCa | — | Igualdade de tipo contra a URI CA/QC | bool | Não lança exceção | — |
TspServiceQualifier | string $qualifierUri, string $criteriaListAssert = 'all', array $policyOidConditions = [], array $keyUsageConditions = [] | Um qualificador de serviço da ETSI com critérios opcionais | — | — | final readonly; constantes FOR_ESIG, FOR_ESEAL, FOR_WSA, QSCD_STATEMENT, NO_QSCD |
EnterpriseCaTrustAnchorBundle | array $anchorsPem, string $bundleVersion, string $bundleSha256 | Pacote de âncoras fixadas; valida o digest fornecido contra as âncoras fornecidas na construção | — | InvalidArgumentException | Obtenha de buildBundle(); não construa à mão; implementa TrustAnchorStoreInterface |
EnterpriseCaTrustAnchorBundle::containsFingerprint | string $anchorDerSha256Hex | Pertencimento de âncora por SHA-256 em hex sobre o corpo DER | bool | Não lança exceção | — |
EnterpriseCaTrustAnchorBundle::computeBundleSha256 | array $anchorsPem | SHA-256 canônico sobre a concatenação de PEM normalizada por quebras de linha | string | Não lança exceção | static |
TslFetchException | — | Sinaliza uma recuperação de TSL falha | — | — | final; estende RuntimeException |
TslParseException | — | Sinaliza uma falha estrutural ou de atualidade | — | — | final; estende RuntimeException |
TslSignatureException | string $reason, string $message | Sinaliza uma falha de verificação XMLDSig com um código de motivo | — | — | final; readonly público $reason (veja os códigos de motivo abaixo) |
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)Códigos de motivo de TslSignatureException: missing_signature, untrusted_signer, invalid_signature, digest_mismatch, unsupported_algorithm, unsupported_transform, expired_anchor.
Contrato de comportamento
Seção intitulada “Contrato de comportamento”- A ordem do pipeline é fixa: fetch, verificação XMLDSig, parse estrutural, portão de obsolescência.
TslPolicyEnforcerretorna umTslDocumentsomente quando os quatro têm sucesso. Uma lista confiável é assinada pelo seu operador de esquema para que as partes confiantes possam checar autenticidade e integridade — ETSI TS 119 612 §5.7.1. TslXmlParseré agnóstico à assinatura por design. Os chamadores devem verificar a assinatura antes de confiar em qualquer campo parseado.TslPolicyEnforcer::verifyXml()impõe essa ordenação.- A invariante de atualidade é imposta em cada fronteira de consumidor. Uma lista cujo
nextUpdatejá passou está expirada e é recusada — ETSI TS 119 612 §5.3.15.verifyXml()compara com a hora atual do sistema;TslDocument::assertFresh()ebuildBundle()comparam com um instante fornecido pelo chamador. - O parse de atualidade é fail-closed. Os campos de data-hora são valores ISO 8601 em UTC com um designador explícito — ETSI TS 119 612 §5.1.3. Um
nextUpdatesem umZexplícito ou offset numérico lançaTslParseException; o valor nunca é reinterpretado no fuso horário local do servidor. buildBundle()chamaassertFresh($now)antes de extrair qualquer âncora e então admite apenas serviços que sejam ao mesmo tempo granted e CA/QC. Granted e withdrawn são as URIs de status de serviço qualificado — ETSI TS 119 612 §5.5.4. CA/QC é a URI de tipo de serviço de CA qualificada — ETSI TS 119 612 §5.5.1.1.- A versão do pacote é derivada do território do esquema e do número de sequência da TSL. O número de sequência é monotônico entre releases — ETSI TS 119 612 §5.3.2. O digest do pacote é um SHA-256 canônico sobre os PEMs das âncoras, e
containsFingerprint()responde ao pertencimento por SHA-256 do DER. - O verificador confia apenas nas âncoras configuradas. Certificados encontrados em
KeyInfoservem como o leaf do assinante e intermediários candidatos; a cadeia deve alcançar uma âncora configurada dentro de profundidade 8, cada elo deve ser temporalmente válido, e um certificado emissor deve carregarbasicConstraintscA=TRUE(maiskeyCertSignquandokeyUsageestá presente). - O perfil de verificação é uma allowlist: RSA ou ECDSA com SHA-256, SHA-384 ou SHA-512; métodos de digest SHA-256, SHA-384 ou SHA-512; apenas canonicalização exclusiva; e exatamente o par de transforms enveloped-signature mais exclusive-C14N na
ds:Referenceque cobre a lista. Qualquer outra coisa falha comunsupported_algorithmouunsupported_transform. TslFetcherrecusa URLs não-HTTPS e aplica uma proteção contra SSRF antes de qualquer egresso. SobNetworkPolicy::STRICT_OFFLINEele serve um corpo previamente cacheado ou lançaNetworkPolicyViolation; nenhuma requisição de saída é jamais enviada.
Casos-limite e modos de falha
Seção intitulada “Casos-limite e modos de falha”- Lista obsoleta. Uma
TslParseExceptionvinda deverifyXml(),assertFresh()oubuildBundle()significa que a fonte de confiança está inutilizável. Trate-a como uma falha operacional de atualização, não como um veredito de assinatura. nextUpdatenão canônico. Um valor sem umZexplícito ou offset numérico lança exceção em vez de fazer o parse de forma leniente. A ETSI TS 119 612 §5.1.3 exige a forma UTCZ; o portão também aceita um offset numérico explícito e rejeita todo o resto.- Deriva de tempo-de-uso.
verifyXml()compara no momento da verificação; um documento mantido em memória além donextUpdateainda falha no portão posteriorbuildBundle($tsl, $now). - Configuração de âncoras vazia.
TslSignatureVerifierrecusa a construção com uma lista de âncoras vazia (InvalidArgumentException). - Nenhum serviço utilizável. Uma lista atual sem serviços CA/QC granted lança
TslParseExceptiona partir debuildBundle(); um pacote vazio nunca é produzido. - Postura offline.
STRICT_OFFLINEsem corpo em cache lançaNetworkPolicyViolation. A consulta ao cache precede a checagem de política, de modo que uma lista em cache mantém a validação em ambiente air-gapped funcionando. - Resposta grande demais ou vazia.
fetch()lê no máximo$maxBytesbytes (padrão 16 MiB); uma lista truncada então falha na verificação de digest mais adiante. Um corpo vazio lançaTslFetchException. - DOCTYPE no XML. Qualquer DOCTYPE é rejeitado antes de o libxml construir uma tabela de entidades, e novamente após o carregamento. Isso fecha as classes de entrada XXE e de expansão de entidades (billion-laughs).
- Múltiplas assinaturas. Apenas a
ds:Signatureenvelopada verificada é removida antes do cálculo do digest; assinaturas irmãs e contra-assinaturas são preservadas. Referências XAdES adicionais são permitidas, mas exatamente umads:Referencedeve cobrir a raiz do documento. - Material de cadeia expirado. Um assinante, intermediário ou âncora expirado ou ainda-não-válido falha com o motivo
expired_anchor.clockToleranceamplia a janela de aceitação simetricamente e assume o padrão0.
Comportamento em modo FIPS
Seção intitulada “Comportamento em modo FIPS”A allowlist do verificador é fixada em RSA e ECDSA com a família SHA-2; SHA-1 e MD5 são estruturalmente excluídos. A aritmética de assinatura roda em criptografia de software agrupada (phpseclib). A NextPDF não faz nenhuma alegação de validação FIPS 140-3 para essa aritmética. O perfil de política de criptografia FIPS 140-3 do Enterprise é documentado junto ao módulo de segurança; ele restringe a seleção de algoritmos e não altera as estruturas de listas confiáveis nem o comportamento fail-closed deste módulo.
Conformidade
Seção intitulada “Conformidade”| Alegação | Norma | Cláusula |
|---|---|---|
| Uma lista confiável cujo Next update já passou é descartada como expirada. | ETSI TS 119 612 | §5.3.15 |
Os campos de data-hora são strings ISO 8601 em UTC com o designador Z. | ETSI TS 119 612 | §5.1.3 |
| O operador de esquema assina a lista confiável para autenticidade e integridade. | ETSI TS 119 612 | §5.7.1 |
| O status de serviço qualificado é a URI de status granted ou withdrawn. | ETSI TS 119 612 | §5.5.4 |
Uma CA qualificada é identificada pela URI de tipo de serviço Svctype/CA/QC. | ETSI TS 119 612 | §5.5.1.1 |
| O número de sequência da TSL começa em 1 e incrementa a cada release. | ETSI TS 119 612 | §5.3.2 |
Todas as cláusulas são parafraseadas; a NextPDF não reproduz texto normativo. A NextPDF não faz nenhuma alegação de conformidade com a ETSI TS 119 612 nem nenhuma alegação de certificação eIDAS. Consumir uma lista confiável não torna uma assinatura, um certificado ou uma saída da NextPDF “qualificada”; a qualificação pertence ao provedor de serviço de confiança sob supervisão do Estado-membro, e o efeito jurídico está fora deste módulo. As restrições do modelo de processamento XMLDSig (transform enveloped-signature, canonicalização exclusiva, referência que cobre a raiz) são documentadas a partir do perfil de verificação do produto; a especificação W3C XML Signature está fora do conjunto de evidências citado. Este módulo decide apenas se uma lista é aceitável como entrada de confiança; a validação de caminho de certificado contra as âncoras resultantes pertence à camada de validação de certificados.
Notas de desenvolvimento
Seção intitulada “Notas de desenvolvimento”- As dependências são interfaces PSR: um cliente PSR-18, uma request factory PSR-17 e um cache PSR-16 opcional. Injete dublês em memória nos testes; nenhum estágio requer acesso à rede ao vivo, exceto um
fetch()frio. - Fixe (pin) a âncora de topo fora de banda. Para listas de Estados-membros, a âncora LOTL autoriza os assinantes das listas; o verificador nunca inicializa a confiança a partir do conteúdo de
KeyInfo. - Polling em segundo plano, processamento de pivot-LOTL e autenticação mutual-TLS ou por proxy estão fora do escopo do fetcher nesta versão. Agende a atualização externamente e refaça o fetch antes de cada
nextUpdate. - Passe o instante de validação, não o instante de construção, para
buildBundle(). Reconstrua o pacote após cada atualização; nunca faça cache de um pacote além donextUpdateda lista de origem. bundleVersiontem a forma observáveltsl-<territory>-seq<sequenceNumber>;rawXmlSha256emTslDocumentdá suporte a registros de evidência e detecção de replay.- Entradas de serviço malformadas são parseadas com valores placeholder defensivos; uma identidade digital malformada que chegue à construção do pacote falha de forma fechada com
InvalidArgumentException. - As classes carregam anotações de fonte de pacote
@since 1.10.0(TslFetchException:3.2.0).TslDocument,TspServiceeTspServiceQualifiersão anotados na fonte com@api.
Veja também
Seção intitulada “Veja também”- Níveis de garantia eIDAS — a página de capacidade que mapeia a evidência de listas confiáveis para Níveis de Garantia.
- Contêineres ASiC — um consumidor de
TslTrustAnchorProvider::buildBundle()para vinculação de confiança de contêiner. - Verificação de assinatura — o lado de verificação AdES/PAdES que consome as âncoras de confiança.
- Segurança — Referência aprofundada — a superfície de segurança Enterprise combinada.
- Assinatura — Referência aprofundada — o produtor de longo prazo PAdES B-LT e B-LTA.
Fronteira de publicação
Seção intitulada “Fronteira de publicação”Esta página documenta apenas o comportamento externamente observável e a superfície pública de API suportada. Caminhos de namespace internos, classes auxiliares, tabelas de mecanismos, nomes de arquivos de runbook e prefixos de ticket estão fora do escopo.