Pular para o conteúdo
getnextpdf.com

Enterprise edição

Início rápido do NextPDF Enterprise

Este tutorial leva você de um projeto vazio a dois resultados Enterprise funcionando. Primeiro, você verifica um PDF assinado existente e lê seu MainIndication. Depois, você eleva um documento assinado para PAdES B-LT com o produtor de longo prazo. Cada etapa mostra a saída ou exceção exata que você deve esperar. O NextPDF documenta capacidade, não certificação: ele não possui nenhuma certificação PAdES ou eIDAS e não concede nenhuma.

Esta capacidade é distribuída no NextPDF Enterprise (nextpdf/enterprise) e é ativada com um envelope de licença de nível Enterprise. Uma implantação sem esse direito de uso não carrega as classes da capacidade. Compare as edições e obtenha uma licença.

  • O Composer está configurado para o repositório privado do NextPDF. Siga primeiro Instalar e autenticar.
  • Você tem seu envelope de licença Enterprise, baixado da sua conta em app.getnextpdf.com. Licenciamento e ativação explica o que é o envelope e para onde ele vai.
  • Para a etapa 3, você precisa de um PDF assinado para verificar. Para a parte B-LT, você também precisa do seu certificado de assinante e acesso de rede aos respondedores OCSP/CRL.

Requeira o pacote Enterprise. Ele depende de nextpdf/core e nextpdf/pro, então o Composer traz toda a pilha:

Terminal window
composer require nextpdf/enterprise
composer show nextpdf/enterprise

Se composer show imprimir o pacote e sua versão, a instalação funcionou. Agora coloque o envelope de licença assinado onde sua implantação o carrega, exatamente como Licenciamento e ativação descreve. Instalar o pacote por si só não concede as capacidades Enterprise; a licença ativada seleciona a edição.

Pergunte ao avaliador de direitos de uso o que sua licença concede. Seu bootstrap obtém o NextPDF\Enterprise\Licensing\LicenseKey verificado durante a ativação; passe-o adiante:

<?php
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Licensing\EntitlementEvaluator;
use NextPDF\Enterprise\Licensing\LicenseKey;
/** @var LicenseKey|null $license The verified license from activation. */
$result = (new EntitlementEvaluator())->evaluate($license);
echo 'status: ' . $result->status->value . PHP_EOL;
echo 'edition: ' . ($result->edition?->value ?? 'none') . PHP_EOL;
echo 'runtime: ' . ($result->runtimeAllowed ? 'allowed' : 'disabled') . PHP_EOL;

Com uma licença Enterprise ativa, você vê:

status: active
edition: enterprise
runtime: allowed

O método por trás desta etapa:

public function evaluate(?LicenseKey $license, ?DateTimeImmutable $now = null): EntitlementResult

Lança ou falha com: ele nunca lança. Uma licença ausente retorna um EntitlementResult fail-closed com EntitlementStatus::NoLicense e runtimeAllowed falso (veja a etapa 4).

Extraia a assinatura de um PDF assinado, depois execute a validação AdES básica. O mecanismo implementa os níveis de validação da ETSI EN 319 102-1; validateBasic() é o fluxo da cláusula 5.2 — estrutura, digest, criptografia da assinatura e a cadeia de certificados:

<?php
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Security\Validation\AdESValidationEngine;
use NextPDF\Enterprise\Security\Validation\CmsSignatureDataExtractor;
use NextPDF\Enterprise\Signature\SignatureExtractor;
$pdf = file_get_contents(__DIR__ . '/contract-signed.pdf');
if ($pdf === false) {
throw new RuntimeException('Could not read contract-signed.pdf');
}
$signatures = (new SignatureExtractor())->extract($pdf);
if ($signatures === []) {
throw new RuntimeException('The PDF carries no signature dictionary.');
}
$engine = new AdESValidationEngine(extractor: new CmsSignatureDataExtractor());
$report = $engine->validateBasic(
$signatures[0]['signedBytes'], // the exact /ByteRange-covered bytes
$signatures[0]['contents'], // the DER CMS SignedData from /Contents
);
echo $report->mainIndication->name . PHP_EOL;
echo ($report->subIndication?->name ?? '(none)') . PHP_EOL;

Para uma assinatura bem formada que passa nas verificações básicas de estrutura, digest, criptografia e cadeia configuradas neste exemplo, você vê:

TOTAL_PASSED
(none)

MainIndication tem exatamente três casos: TOTAL_PASSED, TOTAL_FAILED e INDETERMINATE. O mecanismo é fail-closed: uma verificação que ele não pode estabelecer positivamente resulta em INDETERMINATE, nunca em uma aprovação silenciosa. Uma aprovação aqui é um resultado de validação sob as verificações deste mecanismo, não uma declaração de confiança ou certificação — as âncoras de confiança e as evidências de longo prazo pertencem aos níveis mais profundos na página de verificação.

public function extract(string $pdfData): array

Lança ou falha com: InvalidArgumentException se a entrada não for um PDF válido. Um /ByteRange ou /Contents malformado resulta em strings vazias (fail-closed), nunca em um resultado positivo.

public function validateBasic(string $signedData, string $signature): ValidationReport

Lança ou falha com: ele nunca lança em uma falha de verificação. Cada defeito é mapeado para uma indicação de ValidationReport, por exemplo HASH_FAILURE ou SIG_CRYPTO_FAILURE.

Agora eleve um documento recém-assinado para B-LT. O produtor de longo prazo coleta a cadeia de certificados mais as evidências OCSP/CRL e escreve o Document Security Store (DSS). Ele dá continuidade ao passo de assinatura descrito na página de assinatura, que fornece o buffer de saída, o registro de objetos e o hex de /Contents da assinatura:

use NextPDF\Enterprise\Security\Ltv\LtvManager;
use NextPDF\Security\Signature\CertificateInfo;
use NextPDF\Security\Signature\SignatureLevel;
$certInfo = CertificateInfo::fromPkcs12('/secure/signer.p12', $p12Password);
// $httpClient is any PSR-18 client; it fetches OCSP responses and CRLs.
$ltv = new LtvManager($certInfo, $httpClient, level: SignatureLevel::PAdES_B_LT);
// $buffer, $registry, and $signatureContentsHex come from the signing pass.
$dssObjectNumber = $ltv->enableLtv($buffer, $registry, $signatureContentsHex);

O valor de retorno é o número do objeto DSS para a entrada /DSS do catálogo do documento. O produtor tem como padrão a aplicação estrita de revogação: material de revogação ausente lança uma exceção em vez de emitir silenciosamente um arquivo “B-LT” oco.

public function enableLtv(BinaryBuffer $buffer, ObjectRegistry $registry, string $signatureContentsHex): int

Lança ou falha com: NextPDF\Enterprise\Security\Ltv\LtvException quando a validação da cadeia falha, quando o certificado está revogado ou quando o material de revogação está ausente sob o padrão estrito.

status: no_license — o envelope não está carregado

Seção intitulada “status: no_license — o envelope não está carregado”

A etapa 2 imprime status: no_license e runtime: disabled, e o resultado carrega o aviso No license configured. Enterprise runtime is disabled. Install a license or purchase one at https://nextpdf.dev/pricing. Uma chamada com direito de uso restrito então lança NextPDF\Accelerator\Exception\SpectrumAuthenticationException com o código SPEC-LIC-001, por exemplo Capability '...' requires a valid license. Correção: coloque e ative o envelope conforme Licenciamento e ativação, depois execute novamente a etapa 2.

InvalidArgumentException: Input does not start with %PDF header

Seção intitulada “InvalidArgumentException: Input does not start with %PDF header”

SignatureExtractor::extract() recebeu algo que não é um PDF — um caminho errado, uma leitura vazia ou um download compactado. Verifique o arquivo que você carregou. Uma lista $signatures vazia é diferente: o arquivo é um PDF, mas não carrega nenhum dicionário /Type /Sig, então não há nada para verificar.

LtvException: Strict revocation: LTV warning: no revocation data for certificate at chain position 0

Seção intitulada “LtvException: Strict revocation: LTV warning: no revocation data for certificate at chain position 0”

enableLtv() não conseguiu obter uma resposta OCSP ou uma CRL para um certificado da cadeia, e o padrão estrito recusa-se a escrever uma alegação B-LT sem evidências. Verifique a acessibilidade do respondedor a partir do host, ou passe enforcementMode: RevocationEnforcementMode::PERMISSIVE apenas se você aceitar explicitamente uma execução somente com avisos — nunca rotule essa saída como B-LT para fluxos de trabalho de produção ou conformidade, a menos que a evidência de revogação ausente seja explicitamente aceita e documentada. Relacionado: solicitar B-LTA sem um cliente TSA falha com LtvException: TSA client required for document timestamps.