VerifyKitv0.5.1

Core API Reference

@trexolab/verifykit-core

Headless PDF signature verification engine powered by Rust and WebAssembly. All cryptographic operations -- hash computation, ASN.1 parsing, X.509 chain building, CMS/PKCS#7 validation, and PAdES conformance checking -- run inside the WASM sandbox with no native dependencies.


Functions

createVerifier(config?)

Creates a configured verifier instance for repeated use. Initializes the WASM module on first call.

ts
function createVerifier(config?: VerifyKitCoreConfig): Promise<VerifyKitVerifier>

Parameters:

ParameterTypeRequiredDescription
configVerifyKitCoreConfigNoTrust store and plugin configuration

Returns: Promise<VerifyKitVerifier>

Example:

ts
import { createVerifier } from '@trexolab/verifykit-core'
 
const verifier = await createVerifier({
  trustStore: { certificates: [pemString], mode: 'merge' },
  plugins: [revocationPlugin()],
})
 
const result = await verifier.verify(buffer, 'contract.pdf')
console.log(result.signatures[0].overallStatus) // "valid"
console.log(result.signatures[0].padesLevel)    // "B-T"
 
// Release resources when done.
verifier.dispose()

verifyPdf(input, fileName?)

One-shot signature verification using default configuration. Initializes the WASM module if not already loaded.

ts
function verifyPdf(input: PdfInput, fileName?: string): Promise<VerificationResult>

Parameters:

ParameterTypeRequiredDescription
inputPdfInputYesPDF data as ArrayBuffer, Uint8Array, File, or URL string
fileNamestringNoDisplay name for the file

Returns: Promise<VerificationResult>

Note: verifyPdf() always performs AIA (Authority Information Access) certificate chain resolution. It may make network requests to fetch missing intermediate certificates. To disable AIA, use createVerifier({ enableAIA: false }) instead.

Example:

ts
import { verifyPdf } from '@trexolab/verifykit-core'
 
const buffer = await fetch('/document.pdf').then(r => r.arrayBuffer())
const result = await verifyPdf(buffer, 'document.pdf')
 
for (const sig of result.signatures) {
  console.log(sig.name, sig.overallStatus) // "Alice" "valid"
}

extractPdfMetadata(input)

Extracts document metadata and permissions without performing signature verification.

ts
function extractPdfMetadata(input: PdfInput): Promise<{
  metadata: DocumentMetadata
  permissions: DocumentPermissions
}>

Parameters:

ParameterTypeRequiredDescription
inputPdfInputYesPDF data

Returns: Promise<{ metadata: DocumentMetadata; permissions: DocumentPermissions }>

Example:

ts
import { extractPdfMetadata } from '@trexolab/verifykit-core'
 
const { metadata, permissions } = await extractPdfMetadata(pdfBuffer)
 
console.log(metadata.title)        // "Annual Report 2025"
console.log(metadata.pageCount)    // 42
console.log(permissions.printing)  // "allowed"
console.log(permissions.encrypted) // false

extractSignaturesFromPdf(buffer)

Low-level extraction of raw signature objects from a PDF without performing verification checks.

ts
function extractSignaturesFromPdf(buffer: ArrayBuffer): Promise<any[]>

Parameters:

ParameterTypeRequiredDescription
bufferArrayBufferYesRaw PDF bytes

Returns: Promise<any[]>


initWasm()

Initializes the WASM module. Safe to call multiple times -- subsequent calls return the cached module immediately. Called automatically by verifyPdf(), createVerifier(), and other async functions.

ts
function initWasm(): Promise<any>

Example:

ts
import { initWasm } from '@trexolab/verifykit-core'
 
// Pre-warm during app boot (20-50ms)
await initWasm()

setWasmUrl(source)

Override the WASM source. Call before initWasm() or createVerifier(). This is an escape hatch for environments where you want to load the WASM binary from a custom location instead of using the base64-embedded default.

ts
function setWasmUrl(source: string | URL | ArrayBuffer | WebAssembly.Module): void

Parameters:

ParameterTypeRequiredDescription
sourcestring | URL | ArrayBuffer | WebAssembly.ModuleYesCustom WASM source

Example:

ts
import { setWasmUrl } from '@trexolab/verifykit-core'
 
// Load from a custom URL
setWasmUrl('/custom/path/verifykit_core_wasm_bg.wasm')
 
// Load from an ArrayBuffer
setWasmUrl(myWasmArrayBuffer)
 
// Load from a precompiled WebAssembly.Module
setWasmUrl(myCompiledModule)

Note: As of v0.3.1, the WASM binary is base64-embedded and loads automatically. You only need setWasmUrl() if you want to load from a custom location (e.g., for CSP compliance or to reduce initial bundle parse time).


isWasmReady()

Check whether the WASM module has been initialized.

ts
function isWasmReady(): boolean

Example:

ts
import { isWasmReady, initWasm } from '@trexolab/verifykit-core'
 
if (!isWasmReady()) {
  await initWasm()
}

Trust Store Functions

setTrustStoreConfig(config)

Configure the global trust store used by all subsequent verifications (unless overridden by a verifier instance).

ts
function setTrustStoreConfig(config: TrustStoreConfig): Promise<void>

Example:

ts
import { setTrustStoreConfig } from '@trexolab/verifykit-core'
 
await setTrustStoreConfig({
  certificates: [pemCert1, pemCert2],
  mode: 'merge', // "merge" adds to defaults; "replace" removes defaults
})

resetTrustStore()

Reset the trust store to its default state, clearing any custom certificates.

ts
function resetTrustStore(): Promise<void>

ensureTrustStoreReady()

Ensure the WASM module (and therefore the default trust store) is initialized. Useful for warming up the engine at application startup.

ts
function ensureTrustStoreReady(): Promise<void>

getTrustStore() deprecated

Deprecated. Always returns an object with empty arrays. Trust store contents are managed internally by the WASM engine and are no longer exposed to JavaScript. Use setTrustStoreConfig() or pass trustStore to createVerifier() instead.

ts
function getTrustStore(): TrustStore

Utility Functions

sha256hex(data)

Compute the SHA-256 hash of a Uint8Array and return it as a lowercase hex string. Uses the Rust/WASM implementation.

ts
function sha256hex(data: Uint8Array): Promise<string>

Example:

ts
import { sha256hex } from '@trexolab/verifykit-core'
 
const hash = await sha256hex(new Uint8Array([0x50, 0x44, 0x46]))
// "b8e0e1..."

buf2hex(buf)

Synchronous conversion of an ArrayBuffer to a lowercase hex string. Requires that the WASM module has already been initialized.

ts
function buf2hex(buf: ArrayBuffer): string

oidToName(oid)

Map a dotted OID string to a human-readable algorithm name. Returns the OID unchanged if no mapping exists.

ts
function oidToName(oid: string): string

Supported OIDs:

OIDName
1.2.840.113549.1.1.1RSA
1.2.840.113549.1.1.5SHA-1 with RSA
1.2.840.113549.1.1.10RSA-PSS
1.2.840.113549.1.1.11SHA-256 with RSA
1.2.840.113549.1.1.12SHA-384 with RSA
1.2.840.113549.1.1.13SHA-512 with RSA
1.2.840.10045.2.1EC
1.2.840.10045.4.3.1SHA-1 with ECDSA
1.2.840.10045.4.3.2SHA-256 with ECDSA
1.2.840.10045.4.3.3SHA-384 with ECDSA
1.2.840.10045.4.3.4SHA-512 with ECDSA
1.3.101.112Ed25519
1.3.101.113Ed448
1.3.14.3.2.26SHA-1
2.16.840.1.101.3.4.2.1SHA-256
2.16.840.1.101.3.4.2.2SHA-384
2.16.840.1.101.3.4.2.3SHA-512
1.2.840.113549.2.5MD5
1.2.840.113549.2.2MD2

Example:

ts
import { oidToName } from '@trexolab/verifykit-core'
 
oidToName('1.2.840.113549.1.1.11') // "SHA-256 with RSA"
oidToName('1.2.840.10045.4.3.2')   // "SHA-256 with ECDSA"
oidToName('1.3.101.112')           // "Ed25519"

parseDn(dn)

Normalize a Distinguished Name string by inserting spaces after commas for readability.

ts
function parseDn(dn: string): string

Example:

ts
import { parseDn } from '@trexolab/verifykit-core'
 
parseDn('CN=Alice,O=Acme,C=US') // "CN=Alice, O=Acme, C=US"

computeUnsignedFields(signatures, detectedFields?) deprecated

Deprecated. Always returns an empty array. The WASM engine does not expose unsigned field detection through this function. Unsigned signature fields are now reported directly in the VerificationResult. Remove calls to this function.

ts
function computeUnsignedFields(
  signatures: PdfSignature[],
  detectedFields?: Array<{ fieldName: string; pageNum: number }>,
): UnsignedSigField[]

decompressFlate(data)

Decompress Flate/Deflate-compressed data using the platform DecompressionStream API. Tries both deflate and raw formats. Returns null on failure.

ts
function decompressFlate(data: Uint8Array): Promise<Uint8Array | null>

Platform Exports

isNode

Boolean constant indicating whether the current runtime is Node.js.

ts
const isNode: boolean

ensureCryptoEngine() deprecated

Deprecated. No-op in the WASM engine. The Rust/WASM engine ships its own cryptographic implementation and does not depend on the Web Crypto API. Remove calls to this function.

ts
function ensureCryptoEngine(): Promise<void>

VerifyKitVerifier

Reusable verifier instance returned by createVerifier().

ts
interface VerifyKitVerifier {
  verify(input: PdfInput, fileName?: string): Promise<VerificationResult>
  extractMetadata(input: PdfInput): Promise<{
    metadata: DocumentMetadata
    permissions: DocumentPermissions
  }>
  dispose(): void
}

verify(input, fileName?)

Verify all signatures in a PDF document.

ParameterTypeRequiredDescription
inputPdfInputYesPDF data
fileNamestringNoDisplay name for the result

Returns: Promise<VerificationResult>

extractMetadata(input)

Extract document metadata and permissions without verifying signatures.

ParameterTypeRequiredDescription
inputPdfInputYesPDF data

Returns: Promise<{ metadata: DocumentMetadata; permissions: DocumentPermissions }>

dispose()

Release WASM resources (resets the trust store). Call when the verifier is no longer needed.


Types

VerificationStatus

ts
type VerificationStatus = "valid" | "invalid" | "warning" | "unknown" | "pending"
ValueMeaning
"valid"The check passed successfully.
"invalid"The check failed -- the signature or certificate is not trustworthy.
"warning"The check passed with caveats (e.g., weak algorithm).
"unknown"The check could not be performed (e.g., no revocation data).
"pending"The check has not been executed yet.

PAdESLevel

PAdES (PDF Advanced Electronic Signatures) conformance level detected for a signature, per ETSI EN 319 142.

ts
type PAdESLevel = "B-B" | "B-T" | "B-LT" | "B-LTA"
LevelNameRequirements
"B-B"BasicValid CMS signature with signer certificate and signed attributes.
"B-T"TimestampB-B plus an embedded RFC 3161 timestamp proving when the document was signed.
"B-LT"Long-TermB-T plus embedded validation data (certificates and revocation information).
"B-LTA"Long-Term ArchivalB-LT plus a document timestamp that protects the entire validation data.

VerificationResult

Top-level result returned by verifyPdf() and verifier.verify().

ts
interface VerificationResult {
  fileName?: string            // Name of the verified file
  fileSize: number             // File size in bytes
  fileHash: string             // SHA-256 hex digest of the entire file
  signatures: PdfSignature[]   // All signatures found
  error?: string               // Set if the PDF could not be parsed
}

PdfSignature

Comprehensive information about a single PDF signature, including all eight independent verification checks.

ts
interface PdfSignature {
  index: number                          // 0-based signature index
  name: string                           // Signer display name
  fieldName: string                      // PDF form field name
  subFilter: string                      // e.g. "adbe.pkcs7.detached"
  byteRangeCoverage: boolean             // ByteRange is syntactically correct
  byteRangeCoversWholeFile: boolean      // ByteRange covers all file bytes
 
  // -- Eight independent checks --
  integrityCheck: SignatureCheckResult
  signatureCheck: SignatureCheckResult
  certificateChainCheck: SignatureCheckResult
  expiryCheck: SignatureCheckResult
  timestampCheck: SignatureCheckResult
  revocationCheck: SignatureCheckResult
  algorithmCheck: SignatureCheckResult
  ekuCheck: SignatureCheckResult
 
  // -- Certificate data --
  signerCertificate: CertificateInfo | null
  certificateChain: CertificateInfo[]
 
  // -- Timestamp --
  timestamp: TimestampInfo | null
 
  // -- Signature metadata --
  reason: string
  location: string
  contactInfo: string
  signingTime: Date | null
 
  // -- Overall verdict --
  overallStatus: VerificationStatus
  overallMessage: string
 
  // -- PDF-level properties --
  mdpPermission: number | null           // DocMDP permission (1, 2, or 3)
  isVisible: boolean                     // Visible signature appearance
  padesLevel?: PAdESLevel | null          // Detected PAdES conformance level (null for non-ETSI signatures)
 
  // -- Incremental save tracking --
  notYetVerified?: boolean
  isDeleted?: boolean
  deletedAtRevision?: number
}

Eight Verification Checks:

#CheckFieldWhat it verifies
1IntegrityintegrityCheckThe signed byte ranges have not been altered.
2SignaturesignatureCheckThe CMS/PKCS#7 signature is mathematically valid.
3Certificate ChaincertificateChainCheckA valid chain exists from signer to a trusted root.
4ExpiryexpiryCheckCertificates were within validity period at signing time.
5TimestamptimestampCheckAn embedded RFC 3161 timestamp is present and valid.
6RevocationrevocationCheckThe signer certificate has not been revoked (requires plugin for online checks).
7AlgorithmalgorithmCheckAll algorithms meet minimum security requirements.
8Extended Key UsageekuCheckThe certificate includes the appropriate EKU for document signing.

SignatureCheckResult

Result of a single verification check.

ts
interface SignatureCheckResult {
  label: string              // Human-readable check name
  status: VerificationStatus // Outcome
  detail: string             // Explanation text
  /** Whether the check was actively attempted (e.g., online revocation request made).
   *  Distinguishes "not checked" from "checked but inconclusive." */
  attempted?: boolean
}

CertificateInfo

Parsed X.509 certificate information.

ts
interface CertificateInfo {
  subject: string                    // Distinguished name of the subject
  issuer: string                     // Distinguished name of the issuer
  serialNumber: string               // Certificate serial number (hex)
  notBefore: Date                    // Validity start
  notAfter: Date                     // Validity end
  isExpired: boolean                 // True if notAfter is in the past
  isCA: boolean                      // True if Basic Constraints CA=true
  subjectAltNames: string[]          // Subject Alternative Names
  fingerprint: string                // SHA-256 fingerprint
  sha1Fingerprint?: string           // SHA-1 fingerprint (legacy)
  keyAlgorithm: string               // e.g. "RSA", "EC"
  signatureAlgorithm: string         // e.g. "SHA-256 with RSA"
  keySize?: number                   // Key size in bits
  keyUsage?: string[]                // Key Usage extension values
  extKeyUsage?: string[]             // Extended Key Usage OIDs
  subjectKeyId?: string              // Subject Key Identifier
  authorityKeyId?: string            // Authority Key Identifier
  subjectNameHash?: string           // SHA-1 hash of DER-encoded subject name (hex), used for OCSP
  crlDistributionPoints?: string[]   // CRL distribution point URLs
  ocspUrls?: string[]                // OCSP responder URLs
  caIssuersUrls?: string[]           // CA Issuers URLs
  policies?: string[]                // Certificate policy OIDs
  rawDer?: ArrayBuffer               // Raw DER-encoded certificate bytes
}

TimestampInfo

Information about an embedded RFC 3161 timestamp.

ts
interface TimestampInfo {
  time: Date                          // Timestamp time
  tsaName: string                     // Time Stamping Authority name
  hashAlgorithm: string              // Hash algorithm used
  verified: boolean                   // True if timestamp signature is valid
  tsaCertificates?: CertificateInfo[] // TSA certificate chain
}

DocumentMetadata

PDF document metadata (Info dictionary).

ts
interface DocumentMetadata {
  title: string
  author: string
  subject: string
  keywords: string
  creator: string          // Application that created the PDF
  producer: string         // PDF library that produced the file
  creationDate: Date | null
  modDate: Date | null
  pdfVersion: string       // e.g. "1.7"
  pageCount: number
}

DocumentPermissions

PDF security and permission flags.

ts
interface DocumentPermissions {
  encrypted: boolean
  encryptionMethod: string           // e.g. "AES-256"
  permissionFlags: number | null     // Raw permission integer
  printing: "allowed" | "low-res" | "not-allowed"
  modification: boolean
  copying: boolean
  annotations: boolean
  formFilling: boolean
  accessibility: boolean
  assembly: boolean
}

VerifyKitCoreConfig

Configuration object for createVerifier().

ts
interface VerifyKitCoreConfig {
  trustStore?: TrustStoreConfig
  plugins?: VerifyKitPlugin[]
  wasmUrl?: string | URL
  enableAIA?: boolean
}
PropertyTypeDescription
trustStoreTrustStoreConfigCustom trust store configuration.
pluginsVerifyKitPlugin[]Plugins to extend verification behavior.
wasmUrlstring | URLCustom URL or path to the WASM binary. By default the base64-embedded binary is used -- set this only if you need to load from a custom location.
enableAIAbooleanEnable AIA (Authority Information Access) certificate chain resolution. When true (the default), missing intermediate certificates are fetched from AIA URLs. Set to false to disable network requests for chain building. See AIA Certificate Chain Resolution for details.

TrustStoreConfig

Trust store configuration.

ts
interface TrustStoreConfig {
  certificates?: string[]     // PEM-encoded root CA certificates
  mode?: "merge" | "replace"  // "merge" adds to defaults; "replace" removes them
  url?: string                // URL to fetch certificate bundle from
  refreshInterval?: number    // Refresh interval in milliseconds
}

TrustStore

Runtime trust store contents.

ts
interface TrustStore {
  roots: ArrayBuffer[]         // Root CA certificates (DER)
  intermediates: ArrayBuffer[] // Intermediate certificates (DER)
  all: ArrayBuffer[]           // All certificates (DER)
}

PdfInput

Accepted input types for PDF data.

ts
type PdfInput = ArrayBuffer | Uint8Array | File | string
TypeBehavior
ArrayBufferUsed directly.
Uint8ArrayConverted to ArrayBuffer.
FileRead via file.arrayBuffer().
stringTreated as a URL; fetched via fetch().

VerifyKitPlugin

Plugin interface for extending verification behavior.

ts
interface VerifyKitPlugin {
  name: string
  setup?: (ctx: PluginContext) => void | Promise<void>
  trustStore?: TrustStoreConfig
  revocation?: {
    checkCRL?: (cert: CertificateInfo, urls: string[]) => Promise<RevocationCheckResult>
    checkOCSP?: (cert: CertificateInfo, issuer: CertificateInfo, urls: string[]) => Promise<RevocationCheckResult>
  }
  inputResolver?: (input: PdfInput) => Promise<ArrayBuffer | null>
}
PropertyDescription
nameUnique identifier for the plugin
setupCalled during verifier initialization
trustStoreAdditional trust store certificates to merge or replace
revocation.checkCRLOnline CRL checking callback
revocation.checkOCSPOnline OCSP checking callback
inputResolverCustom input resolver (e.g., fetch from cloud storage)

PluginContext

Context object passed to plugin.setup().

ts
interface PluginContext {
  config: VerifyKitCoreConfig
}

UnsignedSigField

An unsigned signature field detected in the PDF form structure.

ts
interface UnsignedSigField {
  fieldName: string
  pageNum: number
}


AIA Certificate Chain Resolution

When enableAIA is true (the default), the verifier automatically fetches missing intermediate certificates from AIA (Authority Information Access) URLs embedded in certificates. This resolves incomplete certificate chains without requiring you to manually supply intermediate CAs.

How It Works

  1. After initial verification, if certificateChainCheck.status is 'unknown' (chain incomplete), the verifier inspects each certificate's caIssuersUrls extension.
  2. For each URL found, it makes an HTTP GET request (timeout: 5 seconds) to download the certificate.
  3. Downloaded certificates (DER, PEM, or PKCS#7 format) are parsed and added to the trust store.
  4. The signature is re-verified with the enriched trust store.
  5. This process repeats up to a maximum depth of 10 levels, stopping once the chain is complete or no new URLs are found.

Caching

  • Successful fetches are cached for the lifetime of the verifier instance (or globally for verifyPdf()). They are never refetched.
  • Failed fetches are cached for 60 seconds, then retried on the next verification.

Network Behavior

AIA makes outbound HTTP requests from the browser or Node.js process. If this is undesirable (e.g., in air-gapped environments or for privacy reasons), disable it:

ts
const verifier = await createVerifier({ enableAIA: false })

When AIA is disabled, the certificateChainCheck.detail field includes a skip reason (e.g., "offline" or "no-fetch").

verifyPdf() vs createVerifier()

FunctionAIA Behavior
verifyPdf()Always enabled. Uses a global cache. Cannot be disabled.
createVerifier({ enableAIA: true })Enabled (default). Uses a per-instance cache.
createVerifier({ enableAIA: false })Disabled. No network requests for chain building.

If you need control over AIA behavior, use createVerifier() instead of the convenience verifyPdf() function.


RevocationCheckResult

Result returned by revocation check plugins.

ts
interface RevocationCheckResult {
  status: "revoked" | "revokedAfterSigning" | "revokedNoTimestamp" | "good" | "unknown"
  revocationDate?: Date
  reason?: string
  source?: string   // e.g. "OCSP", "CRL"
}
StatusMeaning
"good"Certificate is not revoked.
"revoked"Certificate is revoked. Signature is invalid.
"revokedAfterSigning"Certificate was revoked after the signing timestamp. Signature remains valid.
"revokedNoTimestamp"Certificate is revoked and no timestamp protects the signature.
"unknown"Revocation status could not be determined.