Skip to main content

Verification Web App

The verification web app is a lightweight React application served at signchain.app. Its sole purpose is to verify document signatures when a user scans the QR code on a signed PDF.

Design Goals

  • Zero friction -- No app install, no account, no login
  • Mobile first -- Optimized for phone screens (QR scanning)
  • Client-side decryption -- The encryption key never leaves the browser
  • Fast -- Minimal bundle size, single API call

How It Works

URL Routing

https://signchain.app/v/<base64url(txHash)>#<base64url(key)>
└──── path ────┘ └── fragment ──┘

The React Router matches /v/:txHashB64 and extracts both the path parameter and the URL fragment.

Verification Sequence

Verification sequence

Security: The Fragment Stays Private

The #fragment portion of a URL is never sent to the server in HTTP requests. This is a fundamental property of URLs defined in RFC 3986. This means:

  • The API server never sees the decryption key
  • Network logs and proxies never capture the key
  • Only the browser (and by extension, the user) has access to the key

Technology

AspectChoice
FrameworkReact 19
BundlerVite
CryptoWeb Crypto API (crypto.subtle)
StylingInline styles (no CSS framework)
HostingAny static file host

Web Crypto API Requirement

The Web Crypto API requires a secure context (HTTPS). The verification page will not work over plain HTTP. In production, this is handled by serving from an HTTPS domain. For local development, a self-signed certificate is used via @vitejs/plugin-basic-ssl.

Verification States

The page displays one of three states:

Verified (Green)

All checks passed. Shows:

  • Signer name, email, type, company, position
  • Document hash, signing timestamp, geolocation
  • Transaction hash, composite hash, chain length

Partial Verification (Yellow)

The blockchain anchor exists but the URL fragment (decryption key) is missing. This can happen if:

  • The QR was manually typed without the fragment
  • The URL was shared without the fragment

Shows: transaction hash, composite hash, block time, chain length.

Verification Failed (Red)

The transaction was not found or the API returned an error. Shows the error message.

Bundle Size

The verification app is intentionally minimal:

  • No PDF rendering library
  • No state management library
  • No CSS framework
  • Total bundle: ~70 KB gzipped (mostly React)