VerifyKitv0.13.3
All posts
|5 min read|TrexoLab
signature status iconsignature appearanceadobe readergreen tickpdf viewer

Adobe-Style Green Tick: Signature Appearance Verification in Web Apps

When you open a signed PDF in Adobe Acrobat Reader, you see the verification result directly on the signature field — a green checkmark for valid, a red cross for invalid, a yellow question mark for unknown. Open the same file in almost any web PDF viewer and you get something else entirely: either no verdict at all, or a badge floated over the page in HTML, or — most misleading of all — the grey question mark the signing tool baked into the document, shown forever regardless of whether the signature is good.

VerifyKit brings the Acrobat behaviour to web applications: the status icon is drawn inside the PDF canvas, on the signature field itself, in the field's own rectangle at its scale and rotation, showing the verdict that signature actually got.

Why the placeholder is the wrong answer

A signature field's appearance is authored at signing time, before anyone has verified anything. The signing tool has no idea whether the document will still be intact when you open it, so it draws a neutral placeholder — usually a grey question mark, sometimes nothing.

A viewer that renders the document faithfully renders that placeholder. It is not a bug; it is what is in the file. But for a user it is worse than no icon: it looks like a verdict, and it is not one. A tampered document and a perfectly valid one look identical.

Showing the real result means the viewer has to draw the outcome of verification onto the field, the way Acrobat does.

How you switch it on

After verifyPdf() completes, VerifyKit produces a display copy of the document with the status icons applied:

ts
import {
  swapSignatureAppearances,
  hasAcro6Appearances
} from '@trexolab/verifykit-react'
 
// After verification
const result = await verifier.verify(pdfBytes)
 
// Does this document have signature fields that can carry a status icon?
const hasAcro6 = await hasAcro6Appearances(pdfBytes)
 
if (hasAcro6 || result.signatures.some(s => s.isVisible)) {
  // Returns display-only bytes — the original is untouched
  const displayPdf = await swapSignatureAppearances(
    pdfBytes,
    result.signatures
  )
  // Render displayPdf in the viewer
}

Three properties matter here, and they are the reason this is safe to switch on by default:

  • Verification runs on the original, unmodified bytes. The returned bytes exist only to hand to the renderer. A download gives the user back the original file, byte for byte — which is essential, because a signed PDF that has been re-saved no longer verifies anywhere.
  • Password-protected documents are supported. Encrypted signed PDFs are the case most implementations skip or, worse, corrupt in the attempt.
  • Nothing is invented. Where a signature field cannot carry a status icon, VerifyKit leaves it exactly as the signer authored it rather than drawing something misleading over it.

If you use the React viewer with defaultLayoutPlugin, this is already wired up — the code above is what you need only if you are driving the pipeline yourself.

Adobe Reader parity

Matching Acrobat means matching more than the artwork; it means matching which verdict maps to which icon. Some of these are not obvious:

ScenarioAdobe Reader ShowsVerifyKit Shows
All 8 checks passGreen checkmarkGreen checkmark
Integrity or signature failsRed crossRed cross
Revocation unknown (no online check)Green checkmarkGreen checkmark
Revocation attempted but failedYellow question markYellow question mark
Certificate expired but integrity validYellow question markYellow question mark
Warning on non-critical check (EKU, timestamp)Green checkmarkGreen checkmark

Note rows three and four in particular: a revocation check that was never attempted is not the same as one that was attempted and failed, and Acrobat treats them differently. VerifyKit's SignatureCheckResult carries an attempted flag for exactly this reason.

The same mapping is available on its own if you are building custom UI:

ts
import { getDisplayStatus } from '@trexolab/verifykit-react'
 
const displayStatus = getDisplayStatus(sig)
// 'valid' | 'invalid' | 'unknown'

Signature widget overlays

Beyond the in-canvas icon, the React viewer renders an interactive overlay on each signature field. Every overlay:

  • Shows a coloured border matching the verification status
  • Is clickable — opens the full signature details panel
  • Covers multi-page PDFs where one signature field has widgets on several pages
  • Handles documents where multiple widget annotations share a single signature value

Unsigned signature fields get an overlay too, so an empty signature block is visibly an empty signature block rather than a blank rectangle.

Document timestamps

Document timestamps (ETSI.RFC3161 sub-filter) are visually distinguished from regular signatures with a clock icon. They are archival timestamps for PAdES B-LTA compliance and cover the entire document rather than a single signature.

Why this matters

Users expect a signed PDF to look the same in your web app as it does in Adobe Reader. Without this, signature fields show the signer's placeholder no matter what verification found — which is not a neutral outcome, because a placeholder question mark reads as a verdict to everyone who sees it. Drawing the computed result closes the gap.

Next Steps

Need PDF signature verification in production?

VerifyKit is a commercial SDK — try the live demo, then get in touch for a license.