Apply a PAdES digital signature
At a glance
Section titled “At a glance”Apply a PDF Advanced Electronic Signatures (PAdES) baseline digital signature
to a PDF over NextPDF Connect. Use sign_pdf, which has been re-verified
against the Pro tool provider: that provider registers new SignPdfTool(),
whose protocol name is sign_pdf. sign_pdf is a Pro-tier tool. At boot,
the server probes it with class_exists() and registers it only when the Pro
package is installed.
By default, the tool produces PAdES B-B. It can produce PAdES B-T (B-B plus one RFC 3161 signature-time-stamp) only when the host has wired a timestamp provider into the tool; the request cannot point at a Time Stamp Authority (TSA). Long-term levels (B-LT, B-LTA) and their validation material (DSS, VRI, LTV) are not part of this tool and are out of scope here.
B-T verification basis. The B-T
signature-time-stamprequirement was verified against ETSI EN 319 122-1 §5.3 (the CAdES basis that EN 319 142-1/-2 import by reference), together with RFC 3161, RFC 5652, RFC 5816, and ISO 32000-2 §12.8. An independent validator determines conformance and legal validity.
Install
Section titled “Install”composer require nextpdf/servercomposer require nextpdf/proBind a transport, then confirm that sign_pdf exists with
diagnostic.capabilities. For B-T, the host must construct the tool with a
timestamp provider. Without one, a pades_b_t: true request fails with a
typed error instead of silently downgrading.
Conceptual overview
Section titled “Conceptual overview”sign_pdf computes a byte-range digest over the file, excluding the
signature value placeholder (ISO 32000-2 §12.8.1). It then writes
Distinguished Encoding Rules (DER)-encoded Cryptographic Message Syntax (CMS)
SignedData into the signature dictionary Contents (ISO 32000-2 §12.8.1).
Supported algorithms are RSA-SHA256 (default), RSA + SHA-3 (256/384/512), and
Ed25519. For transports that are not end-to-end confidential, you can wrap
the inbound private_key payload in an optional AES-GCM envelope.
B-T upgrade. With pades_b_t: true and a host-wired timestamp
provider, the signature is upgraded to PAdES B-T: the byte-range hash is
sent to a TSA and a TimeStampToken is embedded (ISO 32000-2 §12.8.5).
B-T is exactly B-B plus one RFC 3161 signature-time-stamp carried as an
unsigned attribute on the CMS SignerInfo (RFC 5652 §5.3).
Unsigned attributes are not covered by the signature, so the B-B signed
digest and its validity are unchanged (RFC 5652 §5.3).
The attribute value is a SignatureTimeStampToken (ETSI EN 319 122-1 §5.3).
B-T adds no Document Security Store (DSS) dictionary, no Validation Related
Information (VRI), no validation material, and no archive-timestamp loop.
Those are the B-LT/B-LTA Enterprise delta and are out of this tool’s scope.
B-T verification basis. B-T is based on ETSI EN 319 122-1 §5.3, RFC 3161, RFC 5652, RFC 5816, and ISO 32000-2 §12.8. An independent validator determines conformance and legal validity.
The flow below shows the host-gated TSA path (the request cannot point at a TSA) and the fail-closed B-T branch (never a silent downgrade).
API surface
Section titled “API surface”| Tool | Tier | Role | Risk tier |
|---|---|---|---|
create_pdf, add_text | Core | Build content | Caution |
sign_pdf | Pro | Apply PAdES B-B (or host-gated B-T) | Approval Required |
output_pdf | Core | Render and return the PDF | Approval Required / Review (base64) |
Tool names are registry protocol names. The tool catalog is the catalog of record. Available tools depend on the installed tier, and long-term-level tools are not present in Pro.
Code sample — Quick start
Section titled “Code sample — Quick start”create_pdf→ build content withadd_text.sign_pdfwithcertificate(PEM),private_key(PKCS#8 PEM), optionalsigner_name,reason, andalgorithm. Omitpades_b_t(or set itfalse) for B-B.output_pdf.
The tool returns this result envelope:
{ "pdf": "<base64 of the signed PDF>", "signature_count": 1, "is_complete": true, "algorithm": "RSA_SHA256", "oid": "<algorithm OID>", "digest": "<digest algorithm>", "level": "PAdES-B-B", "timestamped": false}For a host-gated B-T signature, send pades_b_t: true; level becomes
"PAdES-B-T", and timestamped becomes true.
Code sample — Production
Section titled “Code sample — Production”Sign as the last content operation. Any add_text/add_image after
sign_pdf invalidates the signature. On a non-confidential transport,
wrap private_key in the AES-GCM transport_encryption envelope (12-byte
nonce; 16/24/32-byte key). Verify that the result level matches your
request. A pades_b_t: true request against a tool with no provider
fails explicitly. Handle that error, and do not retry as B-B silently.
Edge cases & gotchas
Section titled “Edge cases & gotchas”- Cert/key mismatch. The tool rejects the request with a clear error; the private key must match the certificate’s public key.
- Malformed PEM / expired certificate. The tool rejects the request; it does not sign with an unparseable or expired certificate by default.
- Content after signing. The tool rejects the request — sign last.
- B-T requested, no provider. The tool returns a typed error: the signature is not produced and is not silently downgraded to B-B.
- Self-signed certificate. The signature applies, but readers show unknown trust. That is expected, not a tool defect.
- Pro absent. With Core only, the server does not register
sign_pdf.
Performance
Section titled “Performance”Signing adds the CMS build and, for B-T, one TSA round-trip; the budget
covers both. The profile is semantic: an RFC 3161 token is inherently
non-reproducible, and the §12.8.1 byte-range digest excludes the signature
value. Use only an AST + signature-metadata comparison.
Security notes
Section titled “Security notes”A signature provides integrity and authentication relative to the signing key. By itself, it does not make a document “secure” or “legally valid”, or guarantee non-repudiation. Those outcomes depend on the certificate, its trust anchor, key custody, and the verifier’s policy, all outside this tool. Encrypting the key payload with the AES-GCM envelope protects confidentiality in transit, not integrity. Treat the private key as a secret, and prefer the transport-encryption envelope on any non-confidential channel.
Conformance
Section titled “Conformance”| Statement | Spec | Clause |
|---|---|---|
| The byte-range digest covers the file and excludes the signature value. | ISO 32000-2 | §12.8.1 |
Contents holds the DER-encoded CMS SignedData. | ISO 32000-2 | §12.8.1 |
For a timestamp, the byte-range hash goes to a TSA and the token is placed in Contents. | ISO 32000-2 | §12.8.5 |
| The B-T time-stamp is an unsigned attribute on SignerInfo. | RFC 5652 | §5.3 |
| Unsigned attributes do not change the B-B signed digest/validity. | RFC 5652 | §5.3 |
| The signature-time-stamp value is a SignatureTimeStampToken. | ETSI EN 319 122-1 | §5.3 |
NextPDF produces the signature structure. An independent validator determines conformance and legal validity. This tool does not produce B-LT/B-LTA.
Commercial context
Section titled “Commercial context”sign_pdf is a Pro-tier tool. The server registers it only when the Pro
package resolves at server boot. PAdES long-term levels (B-LT, B-LTA) and
their validation material (DSS, VRI, LTV) are Enterprise-only and are not
exposed by this tool or this recipe.
Data residency & PII mitigations
Section titled “Data residency & PII mitigations”The certificate and private key transit the request. Use the AES-GCM
transport_encryption envelope on any channel that is not end-to-end
confidential. The signed PDF and signer identity (signer_name, reason)
are document content, so keep them within your data-residency boundary.
The integrator is responsible for deployment-level residency.
Safe telemetry & log scrubbing
Section titled “Safe telemetry & log scrubbing”Never log the private_key payload, the AES-GCM key/nonce, or the
confirmation token. Log the algorithm, the resulting level, and
signature_count, not key material. The tool does not emit key bytes in
its result.
Threat model
Section titled “Threat model”Threats considered: key disclosure in transit (mitigated by the AES-GCM envelope and the host-injected, request-unconfigurable TSA provider); an MCP caller pointing the timestamp at an arbitrary endpoint (prevented because the provider is host-injected, not request-configurable); and post-sign tampering (the byte-range digest detects modification). A threat model documents considered threats and mitigations.
FIPS-mode behavior
Section titled “FIPS-mode behavior”Algorithm selection (RSA-SHA256, RSA + SHA-3, Ed25519) is request-driven. The host’s OpenSSL provides the cryptographic primitives. In a FIPS-constrained deployment, restrict the algorithm at the policy layer and rely on the host’s validated module.
Transport availability
Section titled “Transport availability”| Transport | Available | Notes |
|---|---|---|
| MCP (stdio) | Yes (Pro) | Use the AES-GCM key envelope on stdio. |
| REST | Yes (Pro) | Prefer TLS plus the key envelope. |
| gRPC | Yes (Pro) | Prefer TLS plus the key envelope. |
HITL risk tier
Section titled “HITL risk tier”sign_pdf is Approval Required because it is a destructive, irreversible
operation; the tool advertises a destructive hint. The confirmation gate
applies as it does for any Approval Required tool. output_pdf to a file is
also Approval Required; base64 mode is Review
(HITL risk tiers).
Confirmation gate JSON envelope
Section titled “Confirmation gate JSON envelope”sign_pdf without a valid token returns the challenge envelope:
{ "allowed": false, "challenge": "⚠️ CONFIRMATION REQUIRED\n\nOperation: sign_pdf\nDescription: <tool description>\n\nTo proceed, call sign_pdf again with parameter _confirmation_token: \"confirm_<single-use-hex>\"\nExpires in 300 seconds.", "token": "confirm_<single-use-hex>"}Call again with _confirmation_token set to the token → { "allowed": true }.
Full flow: output-approval.