Skip to content

Apply a PAdES digital signature over NextPDF Connect (Pro)

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.

U-1 caveat. NextPDF does not assert any independent ETSI EN 319 142-1 certification for PAdES B-T. EN 319 142-1 is not in the verification corpus. 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. Support for the B-T profile is not a conformance or legal-validity certification; an independent validator makes that determination.

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.

U-1 caveat (repeated at the B-T claim). B-T support here is not an EN 319 142-1 conformance or legal-validity certification; an independent validator decides. EN 319 142-1 is not in the verification corpus. B-T is based on ETSI EN 319 122-1 §5.3, RFC 3161, RFC 5652, RFC 5816, and ISO 32000-2 §12.8.

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 contentSafe / Caution
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.

StatementSpecClausereference_id
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. It does not assert that any resulting signature is conformant or legally valid; an independent validator decides. 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; it does not assert the absence of vulnerabilities.

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. This tool does not itself assert Federal Information Processing Standards (FIPS) validation.

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.