How to Verify PDF Digital Signatures in the Browser with JavaScript
Digital signatures in PDF documents provide cryptographic proof of document integrity and signer identity. Traditionally, verifying these signatures required server-side processing or desktop applications like Adobe Acrobat. With WebAssembly, you can now verify PDF signatures entirely in the browser — no server uploads, no external services.
Why Browser-Side Verification?
When users upload signed PDFs to a server for verification, the document leaves their device. For contracts, medical records, legal filings, and financial documents, this creates unnecessary privacy risk. Browser-side verification keeps the PDF bytes on the user's device throughout the entire process.
VerifyKit uses a Rust-compiled WebAssembly module to perform all cryptographic operations — RSA, ECDSA, Ed25519 signature validation, SHA-256/384/512 hashing, ASN.1 parsing, and X.509 certificate chain building — directly in the browser's WASM sandbox.
The 8-Point Verification Model
VerifyKit evaluates every PDF signature against eight independent checks:
- Integrity — Verifies the document bytes match the signed byte range. Detects any post-signing tampering.
- Signature — Validates the CMS/PKCS#7 signature is mathematically correct against the signer's public key.
- Certificate Chain — Builds a chain from the signer's certificate to a trusted root CA from the built-in AATL store (119 Adobe-trusted roots).
- Expiry — Confirms all certificates in the chain were valid at signing time.
- Timestamp — Validates any embedded RFC 3161 timestamp token for cryptographic proof of signing time.
- Revocation — Checks whether the signer's certificate has been revoked via CRL or OCSP.
- Algorithm — Enforces minimum cryptographic strength — no MD5/SHA-1, RSA keys must be 2048 bits or more.
- Extended Key Usage — Verifies the certificate permits document signing.
Each check produces its own status (valid, invalid, warning, unknown), and the overall signature status is derived from the combination. This gives you granular visibility into exactly why a signature passed or failed.
Getting Started
Install the React package:
npm install @trexolab/verifykit-reactAdd the provider and viewer to your app:
import { VerifyKitProvider, Viewer } from '@trexolab/verifykit-react'
function App() {
return (
<VerifyKitProvider config={{
workerUrl: 'https://unpkg.com/pdfjs-dist@5.5.207/legacy/build/pdf.worker.min.mjs'
}}>
<Viewer />
</VerifyKitProvider>
)
}That's it. When a user loads a signed PDF, signatures are automatically verified through the full 8-point pipeline and results are displayed with visual status indicators.
Headless Verification (No UI)
For programmatic verification without a viewer UI:
import { createVerifier } from '@trexolab/verifykit-core'
const verifier = await createVerifier()
const result = await verifier.verify(pdfBuffer)
for (const sig of result.signatures) {
console.log(`${sig.signerName}: ${sig.overallStatus}`)
console.log(` Integrity: ${sig.integrityCheck.status}`)
console.log(` Chain: ${sig.certificateChainCheck.status}`)
console.log(` PAdES: ${sig.padesLevel ?? 'N/A'}`)
}This same API works in Node.js 20+, Deno, and Bun — making it possible to share verification logic between client and server.
Built-in Trust Store
The WASM binary ships with 119 Adobe Approved Trust List (AATL) root CA certificates — the same roots that Adobe Acrobat trusts. Certificate chain validation works out of the box without any configuration.
For enterprise deployments, you can extend the trust store with your own root CAs:
const verifier = await createVerifier({
trustStore: {
certificates: [myCorpRootPem],
mode: 'merge', // adds alongside the 119 AATL roots
},
})AIA Chain Resolution
Many PDFs don't embed the full certificate chain. VerifyKit automatically resolves missing intermediate certificates using Authority Information Access (AIA) extensions — fetching intermediates from CA-provided URLs and building the complete chain. This significantly improves verification success rates for real-world documents.
Performance
The Rust/WASM core is 3.7x faster than equivalent JavaScript implementations. The WASM binary is base64-embedded in the JavaScript bundle, so there are no external files to host and no additional network requests. First verification takes 20-50ms for WASM initialization, subsequent verifications are near-instant.
Browser Support
VerifyKit works in all modern browsers that support WebAssembly:
- Chrome 109+
- Firefox 115+
- Safari 16.4+
- Edge 109+
No polyfills needed. No browser extensions required. Just JavaScript and WebAssembly.
Next Steps
- Live Demo — Try signature verification in your browser
- Quick Start Guide — Working code in under 5 minutes
- Core Concepts — Deep dive into the verification model
- Contact Us — Questions about integration or licensing
Ready to verify PDF signatures in your application?
Get started with VerifyKit in under 5 minutes.