JavaScript API
This document covers the JavaScript/TypeScript bindings for tacet via NAPI-RS.
Installation
Section titled “Installation”bun add @tacet/jsnpm i @tacet/jspnpm add @tacet/jsyarn add @tacet/jsQuick Start
Section titled “Quick Start”import { TimingOracle, AttackerModel } from '@tacet/js';import crypto from 'crypto';
const result = TimingOracle .forAttacker(AttackerModel.AdjacentNetwork) .timeBudget(30_000) // 30 seconds .test( { baseline: () => Buffer.alloc(32, 0), sample: () => crypto.randomBytes(32), }, (input) => myCryptoFunction(input) );
if (result.isFail()) { console.error(`Timing leak: ${result.exploitabilityString()}`); process.exit(1);}
// Or use assertion styleresult.assertNoLeak(); // throws TimingLeakError if FailTimingOracle API
Section titled “TimingOracle API”TimingOracle.forAttacker(model: AttackerModel)
Section titled “TimingOracle.forAttacker(model: AttackerModel)”Create a TimingOracle for a specific attacker model.
enum AttackerModel { SharedHardware, // 0.6 ns threshold - SGX, containers PostQuantum, // 3.3 ns threshold - PQ crypto AdjacentNetwork, // 100 ns threshold - LAN, HTTP/2 RemoteNetwork, // 50 us threshold - Internet Research, // ~0 threshold - Detect any difference}Builder Methods
Section titled “Builder Methods”TimingOracle .forAttacker(AttackerModel.AdjacentNetwork) .timeBudget(30_000) // Time budget in ms (default: 30,000) .maxSamples(100_000) // Max samples per class (default: 100,000) .customThreshold(500) // Custom threshold in ns .passThreshold(0.05) // Pass if P(leak) < this .failThreshold(0.95) // Fail if P(leak) > this .seed(12345) // Random seed .showProgress(true) // Print progress to stderr .test(inputs, operation);test<T>(inputs, operation)
Section titled “test<T>(inputs, operation)”Run the timing test.
interface InputPair<T> { baseline: () => T; // Generate baseline input (typically all zeros) sample: () => T; // Generate sample input (typically random)}TimingTestResult
Section titled “TimingTestResult”The test() method returns a TimingTestResult with helper methods:
Outcome Predicates
Section titled “Outcome Predicates”result.isPass() // No leak detectedresult.isFail() // Leak detectedresult.isInconclusive() // Could not decideresult.isUnmeasurable() // Operation too fastresult.isConclusive() // Pass or FailString Formatters
Section titled “String Formatters”result.outcomeString() // "Pass", "Fail", etc.result.exploitabilityString() // "SharedHardwareOnly", "Http2Multiplexing", etc.result.qualityString() // "Excellent", "Good", "Poor", "TooNoisy"result.leakProbabilityPercent() // "12.3%"result.toString() // Human-readable summaryAssertion
Section titled “Assertion”result.assertNoLeak(); // throws TimingLeakError if FailError Classes
Section titled “Error Classes”import { TimingOracleError, TimingLeakError, CalibrationError, InsufficientSamplesError,} from '@tacet/js';
try { result.assertNoLeak();} catch (e) { if (e instanceof TimingLeakError) { console.error(`Leak: ${e.result.exploitabilityString()}`); }}Low-Level API
Section titled “Low-Level API”For advanced use cases, you can use the low-level functions directly.
collectSamples()
Section titled “collectSamples()”Collect timing samples with automatic batch K detection.
import { collectSamples } from '@tacet/js';
const samples = collectSamples( 10_000, () => new Uint8Array(32).fill(0), () => crypto.getRandomValues(new Uint8Array(32)), (input) => myOperation(input));analyze()
Section titled “analyze()”Run complete analysis on pre-collected timing data.
import { analyze, calibrateTimer, configAdjacentNetwork } from '@tacet/js';
const result = analyze( BigInt64Array.from(baselineSamples), BigInt64Array.from(sampleSamples), configAdjacentNetwork(), calibrateTimer().frequencyHz);Adaptive Sampling
Section titled “Adaptive Sampling”import { calibrateSamples, adaptiveStepBatch, AdaptiveState, collectBatches,} from '@tacet/js';
const calibration = calibrateSamples(calBaseline, calSample, config, timer.frequencyHz);const state = new AdaptiveState();
for (const batch of collectBatches(1000, baselineGen, sampleGen, operation)) { const step = adaptiveStepBatch(calibration, state, batch.baseline, batch.sample, config, elapsed); if (step.isDecision) break;}Result Types
Section titled “Result Types”Outcome
Section titled “Outcome”enum Outcome { Pass, // No leak detected Fail, // Leak confirmed Inconclusive, // Cannot decide Unmeasurable, // Operation too fast}Exploitability
Section titled “Exploitability”enum Exploitability { SharedHardwareOnly, // < 10 ns Http2Multiplexing, // 10-100 ns StandardRemote, // 100 ns - 10 us ObviousLeak, // > 10 us}Platform Notes
Section titled “Platform Notes”Timer Resolution
Section titled “Timer Resolution”- x86_64: High resolution (~0.3-0.5 ns) via
rdtsc - Apple Silicon: Lower resolution (~42 ns) via
cntvct_el0
On Apple Silicon, the library automatically uses adaptive batching to compensate.