VerifyKitv0.5.1
All posts
|6 min read|TrexoLab
acro6signature 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 visual status icons directly on the signature field — a green checkmark for valid, a red cross for invalid, and a yellow question mark for unknown. These icons are part of the PDF's signature appearance layers, and VerifyKit brings this same experience to web applications.

How PDF Signature Appearances Work

A PDF signature field contains appearance layers that control what the user sees. There are two common structures:

Legacy Mode (n1 Layer)

Older PDFs use a simple layered structure where /n1 contains the status icon overlay. When verification completes, the viewer replaces the /n1 XObject stream with the appropriate icon.

Acro6 Mode (FRM + n0 Layer)

Adobe Acrobat 6 and later use a more sophisticated structure with a /FRM (frame) layer and /n0 (icon placeholder) sub-layer. The /n0 layer typically starts with a question mark icon, which gets replaced after verification:

  • Green checkmark — Signature is valid. Integrity, cryptographic signature, and certificate chain all pass.
  • Red cross — Signature is invalid. The document was tampered with, the signature is mathematically incorrect, or the certificate was revoked.
  • Yellow question mark — Signature status is unknown. Common when revocation data is unavailable or the root CA is not in the trust store.

How VerifyKit Handles Appearance Swapping

After verifyPdf() completes, VerifyKit provides a swapSignatureAppearances() function that modifies the PDF's signature widget XObject layers in-memory:

ts
import {
  swapSignatureAppearances,
  hasAcro6Appearances
} from '@trexolab/verifykit-react'
 
// After verification
const result = await verifier.verify(pdfBytes)
 
// Check if appearance swap is applicable
const hasAcro6 = await hasAcro6Appearances(pdfBytes)
 
if (hasAcro6 || result.signatures.some(s => s.isVisible)) {
  // Swap appearances — returns modified PDF bytes for display only
  const displayPdf = await swapSignatureAppearances(
    pdfBytes,
    result.signatures
  )
  // Use displayPdf for rendering in the viewer
}

The modified bytes are used only for display — the original PDF is never altered. This approach mirrors exactly how Adobe Reader handles verification: the underlying document stays intact while the viewer renders updated status icons.

Adobe Reader Parity

VerifyKit goes beyond simple icon swapping to match Adobe Reader's status logic:

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

The getDisplayStatus() function re-derives the visual status to match Adobe's behavior:

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

Signature Widget Overlays

Beyond appearance layer swapping, the React viewer renders interactive overlays on signature fields. Each overlay:

  • Shows a colored border matching the verification status
  • Is clickable — opens the signature details panel
  • Supports multi-page PDFs where a single signature field has widgets on multiple pages
  • Handles the PDF Kids array pattern where multiple widget annotations share one signature value

Document Timestamps

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

Customizing Icons

The Acro6 status icons are auto-generated from SVG source files. To customize:

  1. Edit the SVG files in packages/react/src/icons/acro6/
  2. Run node packages/react/scripts/convert-acro6-icons.mjs
  3. The generated file is automatically included in the build

Why This Matters

Users expect signed PDFs to look the same in your web app as they do in Adobe Reader. Without appearance swapping, signature fields display the original placeholder icons (usually a question mark), regardless of verification result. VerifyKit's Acro6 layer support closes this gap, delivering a familiar and trustworthy experience for end users.

Next Steps

Ready to verify PDF signatures in your application?

Get started with VerifyKit in under 5 minutes.