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.
function createVerifier(config?: VerifyKitCoreConfig): Promise<VerifyKitVerifier>Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
config | VerifyKitCoreConfig | No | Trust store and plugin configuration |
Returns: Promise<VerifyKitVerifier>
Example:
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.
function verifyPdf(input: PdfInput, fileName?: string): Promise<VerificationResult>Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
input | PdfInput | Yes | PDF data as ArrayBuffer, Uint8Array, File, or URL string |
fileName | string | No | Display 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:
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.
function extractPdfMetadata(input: PdfInput): Promise<{
metadata: DocumentMetadata
permissions: DocumentPermissions
}>Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
input | PdfInput | Yes | PDF data |
Returns: Promise<{ metadata: DocumentMetadata; permissions: DocumentPermissions }>
Example:
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) // falseextractSignaturesFromPdf(buffer)
Low-level extraction of raw signature objects from a PDF without performing verification checks.
function extractSignaturesFromPdf(buffer: ArrayBuffer): Promise<any[]>Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
buffer | ArrayBuffer | Yes | Raw 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.
function initWasm(): Promise<any>Example:
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.
function setWasmUrl(source: string | URL | ArrayBuffer | WebAssembly.Module): voidParameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
source | string | URL | ArrayBuffer | WebAssembly.Module | Yes | Custom WASM source |
Example:
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.
function isWasmReady(): booleanExample:
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).
function setTrustStoreConfig(config: TrustStoreConfig): Promise<void>Example:
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.
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.
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 passtrustStoretocreateVerifier()instead.
function getTrustStore(): TrustStoreUtility Functions
sha256hex(data)
Compute the SHA-256 hash of a Uint8Array and return it as a lowercase hex string. Uses the Rust/WASM implementation.
function sha256hex(data: Uint8Array): Promise<string>Example:
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.
function buf2hex(buf: ArrayBuffer): stringoidToName(oid)
Map a dotted OID string to a human-readable algorithm name. Returns the OID unchanged if no mapping exists.
function oidToName(oid: string): stringSupported OIDs:
| OID | Name |
|---|---|
1.2.840.113549.1.1.1 | RSA |
1.2.840.113549.1.1.5 | SHA-1 with RSA |
1.2.840.113549.1.1.10 | RSA-PSS |
1.2.840.113549.1.1.11 | SHA-256 with RSA |
1.2.840.113549.1.1.12 | SHA-384 with RSA |
1.2.840.113549.1.1.13 | SHA-512 with RSA |
1.2.840.10045.2.1 | EC |
1.2.840.10045.4.3.1 | SHA-1 with ECDSA |
1.2.840.10045.4.3.2 | SHA-256 with ECDSA |
1.2.840.10045.4.3.3 | SHA-384 with ECDSA |
1.2.840.10045.4.3.4 | SHA-512 with ECDSA |
1.3.101.112 | Ed25519 |
1.3.101.113 | Ed448 |
1.3.14.3.2.26 | SHA-1 |
2.16.840.1.101.3.4.2.1 | SHA-256 |
2.16.840.1.101.3.4.2.2 | SHA-384 |
2.16.840.1.101.3.4.2.3 | SHA-512 |
1.2.840.113549.2.5 | MD5 |
1.2.840.113549.2.2 | MD2 |
Example:
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.
function parseDn(dn: string): stringExample:
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.
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.
function decompressFlate(data: Uint8Array): Promise<Uint8Array | null>Platform Exports
isNode
Boolean constant indicating whether the current runtime is Node.js.
const isNode: booleanensureCryptoEngine() 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.
function ensureCryptoEngine(): Promise<void>VerifyKitVerifier
Reusable verifier instance returned by createVerifier().
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.
| Parameter | Type | Required | Description |
|---|---|---|---|
input | PdfInput | Yes | PDF data |
fileName | string | No | Display name for the result |
Returns: Promise<VerificationResult>
extractMetadata(input)
Extract document metadata and permissions without verifying signatures.
| Parameter | Type | Required | Description |
|---|---|---|---|
input | PdfInput | Yes | PDF 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
type VerificationStatus = "valid" | "invalid" | "warning" | "unknown" | "pending"| Value | Meaning |
|---|---|
"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.
type PAdESLevel = "B-B" | "B-T" | "B-LT" | "B-LTA"| Level | Name | Requirements |
|---|---|---|
"B-B" | Basic | Valid CMS signature with signer certificate and signed attributes. |
"B-T" | Timestamp | B-B plus an embedded RFC 3161 timestamp proving when the document was signed. |
"B-LT" | Long-Term | B-T plus embedded validation data (certificates and revocation information). |
"B-LTA" | Long-Term Archival | B-LT plus a document timestamp that protects the entire validation data. |
VerificationResult
Top-level result returned by verifyPdf() and verifier.verify().
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.
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:
| # | Check | Field | What it verifies |
|---|---|---|---|
| 1 | Integrity | integrityCheck | The signed byte ranges have not been altered. |
| 2 | Signature | signatureCheck | The CMS/PKCS#7 signature is mathematically valid. |
| 3 | Certificate Chain | certificateChainCheck | A valid chain exists from signer to a trusted root. |
| 4 | Expiry | expiryCheck | Certificates were within validity period at signing time. |
| 5 | Timestamp | timestampCheck | An embedded RFC 3161 timestamp is present and valid. |
| 6 | Revocation | revocationCheck | The signer certificate has not been revoked (requires plugin for online checks). |
| 7 | Algorithm | algorithmCheck | All algorithms meet minimum security requirements. |
| 8 | Extended Key Usage | ekuCheck | The certificate includes the appropriate EKU for document signing. |
SignatureCheckResult
Result of a single verification check.
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.
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.
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).
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.
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().
interface VerifyKitCoreConfig {
trustStore?: TrustStoreConfig
plugins?: VerifyKitPlugin[]
wasmUrl?: string | URL
enableAIA?: boolean
}| Property | Type | Description |
|---|---|---|
trustStore | TrustStoreConfig | Custom trust store configuration. |
plugins | VerifyKitPlugin[] | Plugins to extend verification behavior. |
wasmUrl | string | URL | Custom 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. |
enableAIA | boolean | Enable 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.
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.
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.
type PdfInput = ArrayBuffer | Uint8Array | File | string| Type | Behavior |
|---|---|
ArrayBuffer | Used directly. |
Uint8Array | Converted to ArrayBuffer. |
File | Read via file.arrayBuffer(). |
string | Treated as a URL; fetched via fetch(). |
VerifyKitPlugin
Plugin interface for extending verification behavior.
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>
}| Property | Description |
|---|---|
name | Unique identifier for the plugin |
setup | Called during verifier initialization |
trustStore | Additional trust store certificates to merge or replace |
revocation.checkCRL | Online CRL checking callback |
revocation.checkOCSP | Online OCSP checking callback |
inputResolver | Custom input resolver (e.g., fetch from cloud storage) |
PluginContext
Context object passed to plugin.setup().
interface PluginContext {
config: VerifyKitCoreConfig
}UnsignedSigField
An unsigned signature field detected in the PDF form structure.
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
- After initial verification, if
certificateChainCheck.statusis'unknown'(chain incomplete), the verifier inspects each certificate'scaIssuersUrlsextension. - For each URL found, it makes an HTTP
GETrequest (timeout: 5 seconds) to download the certificate. - Downloaded certificates (DER, PEM, or PKCS#7 format) are parsed and added to the trust store.
- The signature is re-verified with the enriched trust store.
- 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:
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()
| Function | AIA 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.
interface RevocationCheckResult {
status: "revoked" | "revokedAfterSigning" | "revokedNoTimestamp" | "good" | "unknown"
revocationDate?: Date
reason?: string
source?: string // e.g. "OCSP", "CRL"
}| Status | Meaning |
|---|---|
"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. |