LM-Kit OneDocs2026.8.10lm-kit.com
Documents/The PDF Toolbox

Digital Signatures

Four endpoints give a PDF a cryptographic life story: pdf-sign binds an identity to the bytes, pdf-verify-signatures judges every signature already there, pdf-timestamp proves the whole file existed at a point in time, and pdf-ltv archives the validation material so the verdicts survive the certificates that produced them. All four follow the toolbox contract: base64 or file id in, a new file id out, password where encrypted input is plausible, and the jobs contract when work runs long. Everything the writers produce is appended incrementally: the original revision stays byte-identical underneath, which is why a signed document can be timestamped and extended without breaking the signatures it already carries.


1The verbs#

Endpoint The concern
POST /lmkit/v1/pdf-sign Apply a PAdES (ETSI.CAdES.detached) signature: invisible, or a visible mark with localized text, a drawn image, or both
POST /lmkit/v1/pdf-verify-signatures The verdict report: every signature judged on four independent axes
POST /lmkit/v1/pdf-timestamp An RFC 3161 document timestamp (ETSI.RFC3161): an authority attests the file's existence, naming no signer
POST /lmkit/v1/pdf-ltv Embed certificates, CRLs, and OCSP responses into the document security store (/DSS, PAdES B-LT)

2Signing#

pdf-sign needs an identity: a PKCS#12 (.p12/.pfx) bundle carrying the certificate and its private key. It resolves from two places, in order:

  1. The request: certificate (base64) plus certificate_password. Nothing is stored; the bundle lives for the duration of the call.
  2. The server: DocumentSigning:CertificateFile plus its password, set once from the admin Signing panel. Requests that carry no certificate sign as the server. A deployment that must never persist the password leaves it empty in configuration and supplies certificate_password per request instead.

When neither exists the request fails immediately with a message that says so; nothing half-signs. Signing is fully managed and in-process: the key never enters an OS key store, which is also what makes the same engine work in the browser and in containers.

The signature is invisible by default: cryptographically complete, no mark on any page. Passing field (a page index and a rectangle in PDF points, origin bottom-left) renders a visible mark instead, and three knobs shape it:

  • Automatic text, the default: who signed, when, and why, composed in the language of appearance_language (fourteen built in; the server's culture otherwise). Scripts beyond the built-in Helvetica compose in English unless appearance_font embeds a font that carries them.
  • appearance_lines replaces the composition with exact custom lines.
  • appearance_image renders a drawn mark (a handwritten stroke, a stamp; PNG keeps its transparency) beside the text, or filling the field when the lines resolve to no text.

certification turns the signature into the document's author signature (DocMDP), declaring which later changes stay legal: no_changes, form_filling, or form_filling_and_annotations. A document carries at most one, and it must be the first signature applied.

When a timestamp authority is available (from the request or from configuration), the signing time is attested by that authority instead of claimed by the signer (PAdES B-T). An explicit empty timestamp_authority opts a single request out.

The response returns the new file id plus a full verification of the stored output, run through the same validator anyone else would use, so the integrity: Valid in it is a checked fact rather than signer bookkeeping.

3Verification#

pdf-verify-signatures reports one verdict per signature, each judged on four axes that deliberately do not blur into each other:

Axis Question Values
integrity Are the signed bytes untouched? Valid, DocumentModified, MalformedSignature, ...
identity Does the signer chain to a trust anchor? Trusted, Untrusted, Unknown
revocation Is the certificate revoked? Good, Revoked, NotChecked
timestamp Is the time proven or claimed? Valid, Untrusted, Invalid, None

The combined status is Valid only when every axis that must hold does; the document-level overall_status is Valid only when every signature is. Untrusted means exactly what it says: no configured anchor reaches the signer. It does not mean the document was tampered with; a modified document reports integrity: DocumentModified. This is the same honesty discipline the rest of the toolbox applies: the report states what was checked and what the check found, never a softer synonym.

Trust is explicit and comes from three places that compose:

  • DocumentSigning:TrustAnchorsDirectory: a folder of certificate files (.cer, .crt, .pem, .der) on the server, typically the organization's issuing CA. Read live, so dropping a file in counts on the next verification.
  • trust_roots on the request: base64 certificates for anchors that matter to one caller only.
  • The OS root store, on by default (DocumentSigning:TrustSystemRoots), so publicly-issued signing certificates verify as Trusted out of the box.

Each result also carries the signer's certificate facts and the embedded chain, the digest algorithm, the recorded reason, the DocMDP level, and covers_entire_document: whether the signature's byte range reaches the end of the file, or later revisions were appended after it (which is normal for a document that was signed and then timestamped or LTV-extended).

4Document timestamps#

pdf-timestamp appends an RFC 3161 document timestamp: a cryptographic attestation that the entire file, signatures included, existed at a point in time. No signer is named; the authority is the witness. The authority comes from timestamp_authority or from DocumentSigning:TimestampAuthority; with neither the request fails immediately. Verification reports these entries as ETSI.RFC3161 with the authority-attested time in timestamp_time.

Timestamps compose with signing rather than replacing it: sign first (the signature may itself carry a B-T timestamp), then timestamp the document to seal the whole revision. Every later timestamp covers everything before it, which is how long-term archives refresh their proof as algorithms age.

5Long-term validation#

A signature is judged against certificates that expire and infrastructure that disappears. pdf-ltv embeds the validation material (certificates, CRLs, OCSP responses) into the document security store (/DSS), so a validator years later finds everything inside the file itself (PAdES B-LT). By default the material already carried by the document's signatures is gathered automatically; certificates, crls, and ocsp_responses add whatever else the archive should hold. A document with no signatures is refused: there is nothing to extend.

The archival chain, stated as calls: pdf-sign, then pdf-ltv, then pdf-timestamp, and the PDF/A conversion runs before signing, never after: PDF/A conversion rewrites the document, and rewriting signed bytes is precisely what integrity: DocumentModified exists to catch.

6Configuration#

The DocumentSigning section, edited from the admin Signing panel, applies live:

Setting Meaning
CertificateFile The server's PKCS#12 signing identity; empty means requests must bring their own
CertificatePassword Its password; empty defers to per-request certificate_password
TimestampAuthority RFC 3161 authority applied when requests name none
TrustAnchorsDirectory Folder of trust anchor certificates for verification
TrustSystemRoots Whether the OS root store also anchors identities (default: on)

The certificate password is a secret: configuration exports mask it, and the panel never echoes it back.

7Agents#

Two MCP tools expose the surface to agents. pdf_verify_signatures ships in the recommended set: judging signatures needs no configuration. pdf_sign signs with the server identity only (certificates never transit a model's context window) and stays held back until an operator who configured an identity deliberately enables it.

8Stated plainly#

  • Sign with the request's identity or the server's; the response re-verifies the output so its verdict is checked, not claimed.
  • Four verdict axes that never blur: untouched bytes, trusted signer, live certificate, proven time.
  • Timestamps and LTV append incrementally; nothing already signed ever breaks.
  • Convert to PDF/A first, sign last: any rewrite after signing is, by design, a broken signature.