Work / Enterprise & Security / PDF Authenticator

No. 31 · Enterprise · Documents · Zero-knowledge

Sign a document.
Store none of it.

A signed PDF can be forged with a $5 app and an afternoon. Universities, banks, and governments still pretend "wet signature scanned" is verification. This portal does not. PAdES signatures, SPKI-pinned verifier, TOTP-secured revocation. Server stores only a 32-byte SHA-256. The document itself never leaves your machine.

32 BStored per document (SHA-256)
PAdESEmbedded CMS signature
SPKIPinned in verify portal
TOTPRevoke with second factor
1Command to deploy

Act I · The Problem

A signed PDF is almost never signed.

"Wet signature, scanned. Looks official. Move on."

  • The forged degree. A free PDF editor, a stolen header, a copied signature. The verifier squints, accepts, hires.
  • The altered transcript. Grades changed in place. Original kept. The "tampered" copy passes the eye test.
  • The document that was real, then revoked. No one can tell the difference. The institution has no way to say "this used to count, now it doesn't".
  • The verifier's privacy bill. To check a document, the holder uploads it. The verifier reads it. Now a third party has the document. Forever.

Act II · The Promise

Four answers. One portal.

The verifier asks one question and gets one of four answers. The document never leaves their browser. The portal never sees its contents.

Genuine

Signed and current.

Embedded CMS signature validates. SPKI pin matches the issuer. Hash recorded. Not revoked.

Tampered

Bytes changed since signing.

Re-computed SHA-256 does not match. The signature math fails. Reject the document. Investigate.

Revoked

Was issued. Has been withdrawn.

Issuer rotated TOTP and revoked. Hash recorded as void. Verifier sees the change in real time.

Unknown

Not in the issuer's registry.

Hash never seen. Could be a draft, a forgery, or a document from a different issuer. Default conservative.

Act III · The Pipeline

Sign, store, verify, revoke. End to end.

  1. Step 01 · Sign

    PAdES signature on the edge

    Admin authenticates via Argon2id-hashed password and TOTP. A Cloudflare Worker forwards a timestamp, nonce, and SHA-256 digest, HMAC-protected, to a Java microservice running Apache PDFBox + Bouncy Castle.

  2. Step 02 · Store

    Only the hash hits D1

    D1 records 32 bytes per document plus metadata. The PDF itself is returned to the admin and never stored. Zero-knowledge in the literal sense.

  3. Step 03 · Verify

    Pinned SPKI in the browser

    The verify portal validates the embedded CMS signature locally and checks the pinned SPKI fingerprint against the issuer. Returns one of four states. Never uploads the document.

  4. Step 04 · Revoke

    One click, second-factor protected

    Issuer signs in, presents TOTP, clicks revoke. CSRF protection. Origin pin. The next verifier sees REVOKED instantly.

Act IV · The Deploy

One command. One VM.

An automated deployment script orchestrates the entire setup on a fresh Ubuntu or Debian VM. System dependencies, nginx, certificates, the Worker, the Java signer, the database wiring. Secrets are generated automatically.

single-command deployment · fresh ubuntu / debian VM
sudo bash -lc 'curl -fsSL \
  https://raw.githubusercontent.com/divyamohan1993/dmj-one-pdf-authenticator/refs/heads/main/one-click-deployment/static/autoconfig.sh?nocache=$(date +%s) \
  | sudo bash -s -- YOUR-D1-DATABASE-ID'

part 01

System setup

dmj-part1.sh installs dependencies, configures nginx, provisions certificates, wires firewall.

part 02

Service deployment

dmj-part2.sh builds and deploys the Worker (TypeScript) and the Java signer (Maven). Dynamic port detection. Auto-reload nginx.

cron

Daily cleanup

Purges expired sessions, replay nonces, and rate-limit buckets. Database stays small. Forever.

CI

Green badges

GitHub Actions CI plus CodeQL run on every push. Both badges live on the repo README.

Act V · Proof

What ships in the repo.

Cloudflare Workers + D1

Edge-served verify portal. Globally distributed. Rate limited. Stores only 32-byte digests plus metadata. The PDF is not on the server. Ever.

HMAC-protected signing gateway

Worker authenticates each signing request to the Java service with timestamp, nonce, and SHA-256. Replay-protected. Origin-pinned.

Apache PDFBox + Bouncy Castle

Signing happens in a Java microservice using PDFBox for PAdES embedding and Bouncy Castle for the CMS signature. Java 17 friendly.

Attribution Assurance Licence

Use it freely. Credit the author. AAL requires attribution in user-facing UI, derivative works, and source. CITATION.cff in the repo.

One-command deploy

autoconfig.sh wraps both deployment phases. Wrangler-authenticated. Secrets generated and stored automatically. Idempotent.

CI / CD plus CodeQL

GitHub Actions. Pipeline badges live on the README. Every push checked. Every release tagged.

If a degree, a transcript, or a permit needs to be real, sign it like it.

I build verification systems where the verifier does not have to trust the issuer's server, and the issuer's server does not have to hold the document. The portal answers one question, four ways. Nothing more.