The pipeline
- Read: the File API reads the PDF into an in-memory byte array. Nothing is posted anywhere.
- Render: pdf.js parses the file in a Web Worker, so large files don't freeze the page, and draws each page to a canvas.
- Place: signature, initials, date and text marks are stored as page coordinates in PDF points, so they land in the same spot whatever the screen size or zoom.
- Write: pdf-lib loads the original file, draws each mark as an image on top of the existing page content, and appends a completion certificate page. The original content streams are kept; if a PDF is encrypted, pdf-lib can't rewrite it, so the pages are rebuilt from high-resolution renders instead and the certificate says so.
- Seal: the file is written with a fixed-length slot in its metadata. SHA-256 is computed over the whole file with that slot zeroed, using
crypto.subtle.digest, and the hash is written into the slot without moving any bytes. - Verify: the verifier repeats the calculation locally. One changed byte anywhere gives a different hash.
What the server does
The site is static files served by Cloudflare Workers. The only API routes handle optional Pro purchases and licence checks, and they receive an email address and payment IDs, never documents. A service worker caches the app shell so it keeps working offline after the first visit.
What it is not
The seal is a hash, not a PKI signature: it proves a file hasn't changed since sealing, but anyone can seal a new file. To tie a document to its signing, the certificate carries a QR link containing the original document's hash, which the verifier compares. If you need certificate-based signatures (PAdES, qualified signatures), you need a provider that issues signing certificates.