Skip to content
getnextpdf.com

Apply a PAdES digital signature

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-stamp requirement 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.

Terminal window
composer require nextpdf/server
composer require nextpdf/pro

Bind 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.

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).

Host-wired RFC 3161 TSAPro SignPdfToolNextPDF Connect serverHost-wired RFC 3161 TSAPro SignPdfToolNextPDF Connect serveralt[host wired a TSA provider][no provider wired]alt[pades_b_t == true]MCP callercreate_pdf then add_text — build content1sign_pdf — certificate, private_key, pades_b_t?2dispatch — Pro tool, class_exists-probed at boot3Byte-range digest, build CMS SignedData — B-B4byte-range hash — request-unconfigurable endpoint5TimeStampToken6Embed token in unsignedAttrs — B-T7Typed error — NOT downgraded to B-B8signed PDF — level B-B or B-T9output_pdf — Approval Required gate10result — pdf, level, timestamped11MCP caller
Diagram
ToolTierRoleRisk tier
create_pdf, add_textCoreBuild contentCaution
sign_pdfProApply PAdES B-B (or host-gated B-T)Approval Required
output_pdfCoreRender and return the PDFApproval 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.

  1. create_pdf → build content with add_text.
  2. sign_pdf with certificate (PEM), private_key (PKCS#8 PEM), optional signer_name, reason, and algorithm. Omit pades_b_t (or set it false) for B-B.
  3. 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.

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.

  • 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.

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.

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.

StatementSpecClause
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.

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.

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.

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.

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.

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.

TransportAvailableNotes
MCP (stdio)Yes (Pro)Use the AES-GCM key envelope on stdio.
RESTYes (Pro)Prefer TLS plus the key envelope.
gRPCYes (Pro)Prefer TLS plus the key envelope.

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).

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.