Signature verification: AdES / PAdES cryptographic verify-side
At a glance
Section titled “At a glance”NextPDF Enterprise cryptographically verifies digital signatures. The verify-side reads Cryptographic Message Syntax (CMS) SignedData or a Request for Comments (RFC) 3161 timestamp token from the PDF, recomputes the digests, checks the signatures, binds each signature to its signing certificate, and validates the certificate chain, including certificate-policy processing, against a caller-supplied trust anchor store. This page describes behavior. It states what is verified, what is rejected fail-closed, which algorithms are supported, and where the trust boundary sits.
This is separate from Validation, which runs read-only structural policy checks and deliberately performs no cryptography. It is also the verify-side counterpart to the Signature producer, which writes PDF Advanced Electronic Signatures (PAdES) B-LT / B-LTA structures.
Install
Section titled “Install”composer require nextpdf/enterprise:^3Conceptual overview
Section titled “Conceptual overview”Verification is evidence-based and fail-closed: a check that cannot be positively established does not produce a positive result. The pieces below combine into one outcome carried by a ValidationReport.
CMS / timestamp-token cryptographic verification. A self-contained, strict, definite-length DER stack parses the CMS SignedData and the RFC 3161 timestamp token. A token is accepted only when it carries exactly one SignerInfo, its signed attributes parse strictly, the signer certificate resolves, the message-digest attribute matches the recomputed digest, the mandatory signing-certificate (ESS signing-certificate-v2) binding holds, and the SignerInfo signature verifies over the re-tagged signed attributes. The digest-matching rule follows the RFC 5652 §5.6 / §5.4 verification model: the recipient recomputes the content message digest, and the signature is valid only when that value equals the messageDigest signed attribute. A verifier never trusts a digest supplied by the producer.
TSA-certificate validation at genTime. The timestamp’s genTime is the UTC instant the token was created (RFC 3161 §2.4.2). The TSA signing certificate is validated at that instant, not at “now”: its extended key usage must be a single, critical id-kp-timeStamping (RFC 3161 §2.3), and its validity window, chain, trust-anchor provenance, and revocation are all evaluated against genTime. A structurally well-formed chain that does not reach a configured trust anchor can never support a positive outcome.
Detached PAdES basic document signatures. A concrete extractor performs real Advanced Electronic Signatures (AdES) / PAdES basic verification for a detached document signature: the message digest is recomputed over the signed byte range and compared, the signature is verified, and the signing-certificate binding is mandatory. This replaces the earlier structural-only fallback. The timestamp verifier and the document-signature extractor share one ESS issuer-and-serial validator, so certificate-binding parsing cannot drift.
Archival DocTimeStamp coverage chain. validateArchivalTimestampChain() validates a chain of trusted DocTimeStamp tokens over the PDF byte ranges as B-LTA archival evidence. Each token’s imprint is bound to the actual ByteRange bytes it covers, the chain follows strict ETSI ordering, every token’s TSA chain is trust-anchored, and the chain must cover the file to its end-of-file marker. It reaches a fully passed outcome only for a complete, trust-anchored, EOF-covering chain.
Certificate-policy processing (RFC 5280 §6.1.4). Path validation applies full certificate-policy processing: a node-structured policy tree, policy mapping with the anyPolicy fallback, and policyConstraints / inhibitAnyPolicy folding, backed by a fail-closed policy-extension DER reader. The path-processing state variables explicit_policy and inhibit_anyPolicy (RFC 5280 §6.1.2) determine whether a non-empty valid-policy tree is required; the wrap-up step intersects the valid-policy tree with the user-initial-policy-set (RFC 5280 §6.1.4). With no required policies and anyPolicy accepted, processing is unconstrained, which is the default and unchanged from earlier behavior.
Supported algorithms
Section titled “Supported algorithms”The verify-side accepts the algorithm set below and fails closed on anything outside it: an unsupported algorithm is a rejected verification, never a silent pass.
| Family | Supported | Notes |
|---|---|---|
| RSA (PKCS#1 v1.5) | rsaEncryption with SHA-2, and the sha*WithRSAEncryption OIDs | Accepted |
| ECDSA | curves P-256, P-384, P-521 | Accepted |
| RSASSA-PSS | — | Unsupported → fail-closed |
| EdDSA | — | Unsupported → fail-closed |
| SHA-3 digests | — | Unsupported → fail-closed |
| SHA-1 | — | Weak: a basic signature that verifies under SHA-1 is degraded to a crypto-constraints failure, not a pass |
API surface
Section titled “API surface”You use the verify-side through the public engine and the Core / Pki contracts. Concrete strategy classes are internal.
| Type | Kind | Role |
|---|---|---|
AdESValidationEngine | class | The verify-side entry point: signature and archival-chain validation. |
AdESValidationEngine::validateArchivalTimestampChain() | method | Validate a trusted DocTimeStamp coverage chain over the PDF byte ranges. |
ValidationReport | result | The structured outcome: overall status plus per-check findings. |
PathValidatorInterface | interface (NextPDF\…\Pki) | The certification-path-validation SPI the engine depends on. |
PathValidationOptions | value object | Policy-processing controls: requireExplicitPolicy, inhibitAnyPolicy, inhibitPolicyMapping, maxPolicyFanout. |
TrustAnchorStoreInterface | interface | The caller-supplied set of trusted anchors the chain is evaluated against. |
The archival-chain method has this signature:
public function validateArchivalTimestampChain( string $pdfBytes, array $dssData = [], ?TrustAnchorStoreInterface $anchors = null,): ValidationReport;It reaches a fully passed outcome only when the DocTimeStamp chain is completely verified, trust-anchored, and covers the file to its EOF marker.
CertificateChainValidator::validate() takes an initial-policy set (the RFC 5280 user-initial-policy-set). The default is anyPolicy, which is unconstrained, so an ordinary chain is unaffected. Pass an explicit set, or set requireExplicitPolicy, to demand a non-empty valid-policy tree.
Code sample — Quick start
Section titled “Code sample — Quick start”use NextPDF\Enterprise\Security\Validation\AdESValidationEngine;
$report = $engine->validateArchivalTimestampChain($pdfBytes, [], $trustAnchors);
if ($report->isTotalPassed()) { // A complete, trust-anchored, EOF-covering DocTimeStamp chain.}Code sample — Production
Section titled “Code sample — Production”use NextPDF\Enterprise\Security\Validation\AdESValidationEngine;use Psr\Log\LoggerInterface;
final readonly class ArchivalEvidenceCheck{ public function __construct( private AdESValidationEngine $engine, private LoggerInterface $logger, ) {}
public function check(string $pdfBytes, TrustAnchorStoreInterface $anchors): bool { $report = $this->engine->validateArchivalTimestampChain($pdfBytes, [], $anchors);
foreach ($report->findings as $finding) { $this->logger->info('archival.finding', [ 'check' => $finding->checkId, 'status' => $finding->status->value, ]); }
// A positive result proves byte-range coverage by a trusted timestamp // chain — it is one input to your decision, not a legal conclusion. return $report->isTotalPassed(); }}Behavioral changes & upgrade notes
Section titled “Behavioral changes & upgrade notes”The verify-side moved from structural / temporal acceptance to full cryptographic verification. If you rely on the older, more lenient behavior, review these changes.
- Fail-closed on a recognisable-but-unverifiable timestamp. A DocTimeStamp or archival token that previously passed on structural and temporal grounds now requires full cryptographic verification: signature, message-digest, and the signing-certificate binding. A token that does not verify no longer yields a positive proof-of-existence; it maps to an indeterminate or failed outcome.
- SHA-1 basic signatures are degraded, not passed. A basic document signature that verifies but uses SHA-1 is reported as a crypto-constraints failure rather than a full pass.
- RFC 5280 §6.1.4 certificate-policy processing is enforced. A chain whose
explicit_policyreaches zero with an empty valid-policy tree now fails, including when a chain-internalpolicyConstraintsrequireExplicitPolicydrives it. Default, unconstrained chains (no required policies,anyPolicyaccepted) are unaffected. - Constructor signature change (BC break).
AdESValidationEngine::__construct()now types its$chainValidatorparameter as thePki\PathValidatorInterfaceSPI, lazily defaulted toPki\CertificateChainValidator::withDefaults(). It was previously the concreteLtv\CertificateChainValidator. A caller that injected the concrete LTV validator must inject the Pki SPI implementation instead. The Pki validator wraps the same structural path engine and adds name constraints and policy processing; it is a no-op for conformant default inputs.
Edge cases & gotchas
Section titled “Edge cases & gotchas”- Unsupported algorithm ≠ inconclusive. RSASSA-PSS, EdDSA, and SHA-3 are rejected fail-closed, not deferred. If your signers use them, this verify-side will not return a positive result.
- Trust is anchor-relative. Verification is always relative to the trust anchor store you supply. An empty or wrong anchor set yields a not-trusted outcome regardless of cryptographic correctness.
- genTime, not now. The TSA certificate is judged at the token’s
genTime. A TSA certificate that has since expired can still support a token created while it was valid; a certificate not yet valid atgenTimecannot. - EOF coverage. The archival chain must cover the document to its EOF marker. A timestamp that covers only a prefix of the file does not establish whole-document coverage.
- Not-proven-revoked is not Good. A
Validverdict needs a conclusively non-revoked status. If both OCSP and CRL come back Unknown or Unavailable, even a cryptographically sound, chain-valid, trust-anchored signature resolves toIndeterminate. Supply embedded OCSP/CRL Good material for the signer certificate to reachValid.
Performance
Section titled “Performance”Verification runs in process over the supplied PDF bytes and the embedded validation material; cost scales with chain length and the number of timestamps. Verification makes no network round trips. Revocation and trust material come from what the caller supplies or what is embedded in the document. Verification is deterministic: the same inputs and the same trust anchors produce the same report.
Security notes
Section titled “Security notes”- Fail-closed is the default. Every acceptance step refuses material it cannot positively verify. This prevents a document from advertising validity that the engine never established.
- Append-after-timestamp is defeated by EOF coverage. Because each archival timestamp’s imprint is bound to the actual
ByteRangebytes and the chain must reach EOF, content appended after a timestamp is not covered by it and does not gain its evidentiary weight. - Treat input as hostile. PDF bytes, embedded CMS, and timestamp tokens from untrusted sources are parsed by a strict definite-length DER reader that rejects malformed or indefinite-length encodings.
Data residency & PII mitigations
Section titled “Data residency & PII mitigations”Verification is in process and local, with no network I/O. Certificates and signatures carry subject identity; apply your own retention and minimization controls to reports and any extracted certificate data.
Safe telemetry & log scrubbing
Section titled “Safe telemetry & log scrubbing”Findings carry check identifiers and statuses. Some diagnostics can echo certificate subject names or serial numbers; scrub or redact those fields before you forward logs to shared sinks.
Scope boundaries
Section titled “Scope boundaries”State these boundaries in user-facing output so a positive result is not over-read.
validateArchivalTimestampChain()proves byte-range coverage, not xref reachability. It establishes that a trusted timestamp chain cryptographically covers the document’s byte ranges to EOF. It does not perform xref-level orstartxrefobject-reachability analysis; that is out of scope by design. The EOF-coverage rule, together with trust anchoring, defeats append-after-timestamp attacks, not object-graph analysis.- Out of scope by design. Evidence Records (RFC 4998 / RFC 6283); verification of RSASSA-PSS, EdDSA, or SHA-3 timestamp tokens; trusted-list (TSL) and qualified-TSA integration; and online TSA-revocation fetching are not provided by this verify-side. Revocation is evaluated from material already available to the verifier.
Conformance
Section titled “Conformance”| Behavior | Reference | Status |
|---|---|---|
Signature value / timestamp token stored DER-encoded in /Contents | ISO 32000-2 §12.8.1 | Parsed and verified |
| Document timestamp dictionary | ISO 32000-2 §12.8.5 | Read for the archival chain |
| Recipient recomputes the content digest; it must equal the messageDigest attribute | RFC 5652 §5.6 / §5.4 | Enforced |
TSA certificate carries a single critical id-kp-timeStamping EKU | RFC 3161 §2.3 | Checked at genTime |
| genTime is the UTC creation instant | RFC 3161 §2.4.2 | Used as the validation instant |
Policy-processing state variables (explicit_policy, inhibit_anyPolicy) | RFC 5280 §6.1.2 | Processed |
| Wrap-up intersects the valid-policy tree with the user-initial-policy-set | RFC 5280 §6.1.4 | Enforced |
| DSS entries and document time-stamps for long-term signatures | ETSI EN 319 142-2 §5.5 | Validated as archival evidence |
All clauses are paraphrased. NextPDF does not reproduce normative text; consult the published standards for the authoritative wording. NextPDF makes no AdES / PAdES certification claim. The verify-side implements the cryptographic checks described by the cited specifications; it is not a certified validation service and produces no third-party attestation.
FIPS-mode behavior
Section titled “FIPS-mode behavior”When the Enterprise FIPS profile is active, the constraint applies to the digest and signature algorithms the verifier accepts. The verification logic, including digest recomputation, signature checks, certificate-binding, and path validation, is unchanged.
Threat model
Section titled “Threat model”| Asset | Adversary | Risk | Mitigation |
|---|---|---|---|
| Timestamp token | Forged or altered token | A false proof-of-existence | Full cryptographic verification; fail-closed on anything unverifiable |
| TSA certificate | Untrusted issuer | Apparent trust the verifier should not assert | Chain validated to a caller-supplied anchor at genTime; untrusted chain never passes |
| Document bytes | Append-after-timestamp | Content gains a timestamp’s weight without coverage | Imprint bound to actual ByteRange bytes + EOF-coverage rule |
| Weak algorithm | Downgrade to SHA-1 / unsupported scheme | A weak signature read as valid | SHA-1 degraded; RSASSA-PSS / EdDSA / SHA-3 fail-closed |
Edition gate
Section titled “Edition gate”This verify-side is an Enterprise capability and ships in the nextpdf/enterprise package. NextPDF Core detects signature presence and produces B-B / B-T signatures, but it does not provide this cryptographic verify-side. Get a license.
License feature flag
Section titled “License feature flag”The verify-side is gated by the Enterprise edition (license_feature_flag: enterprise). It resolves through the Core and Pki contracts; the public application programming interface (API) does not change on an edition upgrade.
Behavior contract
Section titled “Behavior contract”- A CMS or timestamp token is accepted only with exactly one
SignerInfo, strictly-parsed signed attributes, a resolved signer certificate, a matching message-digest, the mandatory signing-certificate binding, and a verifyingSignerInfosignature. - The TSA certificate is validated at the token’s
genTime: a single criticalid-kp-timeStampingEKU, validity window, trust-anchored chain, and revocation. - A
Validverdict additionally requires a conclusively non-revoked status: at least one authoritative Good (a verified-good OCSP response, or a fresh CRL placing the serial outside an unexpired list). A status that is merely not-proven-revoked, where OCSP and CRL are both Unknown or Unavailable, resolves toIndeterminate, neverValid(ETSI EN 319 102-1: revocation status-unavailable → INDETERMINATE). Because the CRL-fallback path attests only list freshness and not per-serial revocation, a CRL-only chain without a Good OCSP is commonlyIndeterminate. validateArchivalTimestampChain()reaches a fully passed outcome only for a complete, trust-anchored, EOF-covering DocTimeStamp chain; it proves byte-range coverage, not xref reachability.- Certificate-policy processing follows RFC 5280 §6.1.4; default unconstrained chains are unaffected.
- Supported algorithms are RSA (PKCS#1 v1.5 with SHA-2) and ECDSA (P-256/384/521); RSASSA-PSS, EdDSA, and SHA-3 fail closed; SHA-1 is degraded.
NDA scan status
Section titled “NDA scan status”This public page describes externally observable verify-side behavior only. It names the public engine, the Pki / trust-anchor contracts, and the validateArchivalTimestampChain() method through the supported surface. The concrete DER, CMS, policy-processor, and path-validator internals are in the gated deep reference under the nondisclosure agreement (NDA).
Core fallback
Section titled “Core fallback”NextPDF Core detects the presence of a signature and produces B-B / B-T signatures, but it does not cryptographically verify CMS or timestamp tokens, validate an archival chain, or run RFC 5280 §6.1.4 policy processing. A Core-only deployment has no equivalent verify-side; see Security / Signing (Core).
Pro fallback
Section titled “Pro fallback”NextPDF Pro adds signing strategies and e-invoice handling, but it does not provide this cryptographic verify-side; archival-chain validation and certificate-policy processing ship in nextpdf/enterprise only.
Enterprise boundary note
Section titled “Enterprise boundary note”The verify-side is described at the behavior level. The strict DER stack, the CMS parser, the policy processor, and the path-validator internals are out of scope for the public surface and are not reproduced here.
Deployment boundary
Section titled “Deployment boundary”Verification depends on the trust anchor store and any revocation material the caller supplies or that is embedded in the document. NextPDF Enterprise evaluates that material; it does not operate a trust list, a TSA, or a revocation service. The operator owns anchor selection and the freshness of embedded revocation material.
Legal-compliance boundary
Section titled “Legal-compliance boundary”This page is marked export_control_class: legal-review-required; it concerns cryptographic verification. Legal sign-off is required before the publish flag is set. A positive verification result is a cryptographic statement about the document’s signatures and timestamps. It is not a legal opinion, an eIDAS qualification determination, or a certification. NextPDF makes no AdES / PAdES certification claim. Consult your own compliance and legal advisers for your regulatory obligations.
See also
Section titled “See also”- Signature: PAdES B-LT / B-LTA producer — the producer side.
- Validation — in-process structural policy checks (no cryptography).
- Archive: DSS, VRI, LTV health — long-term archival and LTV health.
- Security / Signing (Core) — CMS, RFC 3161, RFC 5280 path validation, OCSP/CRL.
- PAdES baseline mapping — B-B, B-T, B-LT, B-LTA across editions.
- PAdES · DSS · LTV — glossary terms.