DEV Community

leiferiksson8493
leiferiksson8493

Posted on

PDF Digital Signatures: What Contract Evidence They Prove and Leave Open

Short answer: a PDF digital signature can show who controlled a signing key, what bytes were signed, and whether those bytes changed afterward; it does not prove that the signer understood the contract, had authority, or performed the promised work.

That distinction matters in a one-person SaaS. I care about revenue per hour, so I want a contract workflow that settles a dispute without turning me into a part-time forensic analyst. A green “signature valid” badge is useful evidence. It is not a complete story.

The constraint that changes the design

For contract signing, the expensive failure is usually not a broken PDF renderer. It is an overconfident interpretation of evidence. A customer can present a file whose cryptographic signature is intact while the wrong person clicked the button, an approval rule was bypassed, or the document was signed before an important attachment was added.

I model the signed artifact as three separate claims:

Claim Evidence a PDF signature can provide Evidence it cannot provide by itself
Integrity The signed byte ranges still match the digest recorded in the signature That every relevant business attachment was included
Key control A certificate chain can connect a public key to an identity assertion That the human using the key was the intended employee at that moment
Time A trusted timestamp can establish a time for the signature value That the parties agreed to every event in the surrounding timeline

This is the decision rule I ship: treat the signature as a tamper-evident receipt, then collect identity, authority, and consent evidence beside it. Those are different records with different owners.

Small rule. Keep them separate.

What does a PDF digital signature prove, and what does it not prove?

PDF signatures are defined within the PDF specification, including ISO 32000-2. In a typical workflow, the signer application calculates a digest over designated byte ranges, signs that digest with a private key, and embeds the result in a signature dictionary. A verifier recalculates the digest and checks the certificate path. If either check fails, the file has a meaningful integrity or trust problem.

That process can prove that the checked bytes have not changed since signing. It can also support an attribution claim when the certificate was issued under a policy the relying party accepts. The strength of that attribution depends on the certificate profile, revocation evidence, timestamp practice, and the identity checks behind issuance.

It cannot prove intent. It cannot prove that the signer read every page. It cannot prove that a manager had authority under an internal delegation policy. It cannot prove that a clause was fair, that a signature was not obtained through coercion, or that a delivery obligation was met.

The phrase “signed PDF” hides another boundary: incremental updates. PDF allows later revisions to be appended. Some revisions are permitted after signing, such as adding another signature or approved form data. Other changes should invalidate the earlier signature. Your verifier needs to report which revisions were covered and which were appended, not collapse everything into valid or invalid.

No magic badge.

I once treated that boolean as a complete result in a prototype. The integration passed its happy-path tests, then a reviewer asked whether a post-signing annotation was covered. We had no answer in the audit record. The fix was not a clever parser. It was storing the byte-range result, certificate details, timestamp status, and revision summary as separate fields.

Build the smallest useful verification record

The implementation below is deliberately boring. It is an application-level record, not a replacement for a standards-compliant PDF verifier. The verifier library supplies the facts; this function prevents the rest of the product from inventing a stronger claim.

type SignatureCheck = {
  integrity: "pass" | "fail" | "unknown";
  signerIdentity: "identified" | "unresolved";
  timestamp: "trusted" | "missing" | "untrusted";
  revisionsAfterSigning: "none" | "allowed" | "unexpected" | "unknown";
};

type ContractEvidence = {
  conclusion: "cryptographically-intact" | "needs-review";
  reasons: string[];
};

export function classifySignature(check: SignatureCheck): ContractEvidence {
  const reasons: string[] = [];

  if (check.integrity !== "pass") {
    reasons.push("The signed byte ranges were not confirmed.");
  }
  if (check.signerIdentity !== "identified") {
    reasons.push("The certificate identity needs independent review.");
  }
  if (check.timestamp !== "trusted") {
    reasons.push("No trusted signing time was established.");
  }
  if (check.revisionsAfterSigning === "unexpected") {
    reasons.push("A post-signing revision needs review.");
  }

  return {
    conclusion: reasons.length === 0 ? "cryptographically-intact" : "needs-review",
    reasons,
  };
}
Enter fullscreen mode Exit fullscreen mode

The output intentionally says “cryptographically-intact,” not “legally binding.” Legal effect varies by jurisdiction, signature type, contract language, and evidence outside the file. Your product should preserve the raw verification report so counsel or an auditor can inspect the assumptions later.

Where teams get burned

The first trap is identity substitution. A certificate can identify an account, organization, or device according to its issuance policy. That is not the same as proving the individual’s employment status or authority to sign this particular contract. Keep the invitation, authentication event, role assignment, and approval record in an append-only event log.

The second trap is missing context. If the contract references an exhibit, price sheet, or game asset license stored elsewhere, hash and retain the exact version that was presented. A signature over the main PDF does not magically cover a mutable link.

The third trap is clock confusion. The PDF creation time is metadata supplied by a producer. A trusted timestamp, when present and properly validated, is stronger evidence for when a signature value existed. Neither one proves when a human first saw the offer.

The fourth trap is verification drift. Certificate revocation status and validation policies change. Store the validation material and policy version used at verification time. Re-running a check years later may produce a different status even when the signed bytes are unchanged. In practice, that means retaining the certificate chain, revocation responses, timestamp token, verifier version, and policy identifier with the contract record. It also means making the audit export boring enough that another engineer can reproduce the decision without access to your production database. When a customer asks why a signature was accepted, “the dashboard was green” is not a durable answer; a dated, attributable set of inputs is.

Your mileage may vary here: retention periods, accepted certificate policies, and the legal weight of electronic signatures differ by country and contract type. I’m not sure a single dashboard can express that nuance well, so my UI exposes the evidence fields and links to the policy instead of showing one oversized green check.

What I would change at scale

At low volume, a managed signing service can save hours that I would rather spend shipping weekly. At higher volume, the bottleneck becomes evidence operations: key custody, revocation data, timestamp validation, access controls, and reproducible audits. The right boundary is the one that lets you replace a verifier without rewriting your contract domain model.

I would add four tests before adding features:

  1. A byte change inside a signed range must produce an integrity failure.
  2. An allowed incremental update must be reported as a revision, not silently ignored.
  3. A certificate with an unresolved chain must not be labeled identified.
  4. A contract whose exhibit hash differs from the signing record must require review.

The catch is that this approach is not suitable when your process needs a full legal-signature provider, qualified certificates, or jurisdiction-specific identity proofing. Use a specialist workflow when those controls are a requirement. Keep the evidence model anyway; portability is easier when your business records do not depend on one verifier’s wording.

The practical payoff is modest but real: fewer arguments about what “valid” means, faster handoffs to counsel, and less founder time spent reconstructing a signing event from email threads. A PDF signature proves a narrow technical fact. Design the surrounding system to preserve the broader facts you actually need.

References

Top comments (0)