Verifying signatures

WebPDF checks the digital signatures of a PDF right in the browser, with Web Crypto: whether the signed part is intact, who signed and when, whether a certificate path leads to an anchor you trust, and whether a certificate was revoked. The PDF never leaves the browser; only certificate status and trust lists are fetched. This article shows how to verify signatures, choose what to trust, and show the results.

Verification is automatic

A signed file verifies its signatures by itself, in idle time after its first pages draw, and fires a verify event. Its signed property gives the worst result, and CSS sees it as a custom state:

js
const file = document.querySelector("pdf-file");
file.addEventListener("verify", () => console.log(file.signed)); // "verified"
css
body:has(pdf-file:state(invalid)) .warning {
  display: block;
}

verify() returns the rows themselves, one per signature, newest first: their status, their certificate path, their time and their revocation checks. See Signature verification results for every field.

StatusMeans
"verified"Intact, by a trusted signer, not revoked.
"unknown"Could not be checked.
"untrusted"The signer is not trusted: no trust anchors, or an unknown or self-signed issuer.
"expired"A certificate was not valid at signing time.
"revoked"A certificate was revoked.
"invalid"Broken, or the signed part was changed.

Choosing what to trust

Nothing is trusted by default: without trust anchors, every intact signature is untrusted. Give a file anchors with three attributes, which you can also put on the <script> for every file:

trust:src

The URL of a certificate file: PEM, DER or a PKCS #7 bundle.

trust:srcdoc

Certificates written inline, as PEM or base64.

trust:stores

Well-known root stores, fetched fresh from their publishers: aatl (the Adobe Approved Trust List), eutl (the EU trusted lists), ms (Microsoft's document signing roots) and moz (Mozilla's email roots).

Trusting your own root

This file is signed by a demo authority, and trusts its root certificate:

html
<pdf-file id=s src=//new.webpdf.pro/signed.pdf trust:src=//new.webpdf.pro/demo-root.pem signatures></pdf-file>
<pdf-page of=s scale=0.6></pdf-page>

Anchors on the script add up with each file's own; see Multi-homed attributes. Changing an anchor verifies the signatures again, without loading the file again.

Revocation

For a trusted signer, WebPDF checks online whether the certificates were revoked, with OCSP and CRLs, through its proxy; revocation data embedded in the PDF is always used. break=revocation keeps the checks offline, and break=verify turns verification off altogether.

Signature cards

Every page puts a hotspot over each visible signature field: click it for a card with who signed, when, and every check. With signatures on a page, a file or the script, the page also shows compact cards in place, and signatures without a visible field show their cards in its top right corner. On a page with controls, Alt S toggles the cards, and Alt Shift S toggles them on every page.

A click on a signature fires a cancelable signature event; call preventDefault() to show your own interface instead of the card:

js
page.addEventListener("signature", (event) => {
  event.preventDefault();
  const [row] = event.detail.signatures;
  console.log(row.status, row.certificate?.subjectCN);
});

The cards are parts too, and their colors custom properties, such as --pdf-page-signature-verified-color.

Requirements

See also