export { deriveTokenBytes, deriveToken, deriveDirectionalPair, type DirectionalPair } from 'spoken-token'; export { MAX_TOLERANCE, MAX_INPUT_CHARS } from 'spoken-token'; import { type TokenEncoding } from 'spoken-token'; /** * CANARY-DURESS: Derive raw duress token bytes for a specific identity. * * Algorithm: HMAC-SHA256(secret, utf8(context + ":duress") || 0x00 || utf8(identity) || counter_be32) * * The null-byte separator between the context suffix and identity prevents concatenation * ambiguity (e.g. context="x:duress" + identity="" vs context="x" + identity=":duress"). * * NOTE: Returns raw bytes without collision avoidance. Use deriveDuressToken() * for encoded output with guaranteed non-collision against the normal token. * * @param secret - Shared secret (hex string or Uint8Array, minimum 16 bytes). * @param context - Context string for domain separation (e.g. `'canary:group'`). * @param identity - Member pubkey or identifier (must be non-empty). * @param counter - Time-based or usage counter (uint32). * @returns Raw 32-byte HMAC-SHA256 digest. * @throws {RangeError} If secret is too short or counter is out of range. */ export declare function deriveDuressTokenBytes(secret: Uint8Array | string, context: string, identity: string, counter: number): Uint8Array; /** * CANARY-DURESS: Derive an encoded duress token with collision avoidance. * * If the duress token collides with any normal verification token within * ±(2 × maxTolerance) counter values (at the encoding level), re-derives with * incrementing suffix bytes (0x01, 0x02, ..., 0xFF) until distinct. * The 2× factor accounts for worst-case counter drift between deriver and verifier. * If all 255 suffixes collide (astronomically unlikely), throws an error * rather than failing open. * * **maxTolerance is required** — it must match the tolerance used by verifiers. * Using an insufficient value allows duress tokens to collide with normal tokens * at distant counters, causing silent alarm suppression. * * **identities** — when provided, the forbidden set also includes per-member * normal tokens for all identities across the collision avoidance window. * Without this, a duress token for identity A could collide with the normal * per-member token for identity B, causing false duress detection. * * @param secret - Shared secret (hex string or Uint8Array, minimum 16 bytes). * @param context - Context string for domain separation (e.g. `'canary:group'`). * @param identity - Member pubkey or identifier for the duress signaller. * @param counter - Time-based or usage counter (uint32). * @param encoding - Output encoding format (default: single word from en-v1 wordlist). * @param maxTolerance - Counter tolerance window used by verifiers; must match their value. * @param identities - All group member pubkeys for cross-member collision avoidance. * @returns Encoded duress token string guaranteed distinct from all normal tokens in the window. * @throws {RangeError} If maxTolerance is negative, exceeds MAX_TOLERANCE, or is not an integer. * @throws {Error} If collision avoidance fails after 255 retries. */ export declare function deriveDuressToken(secret: Uint8Array | string, context: string, identity: string, counter: number, encoding: TokenEncoding | undefined, maxTolerance: number, identities?: string[]): string; /** Result of verifying a token. */ export interface TokenVerifyResult { /** 'valid' = matches normal token, 'duress' = matches a duress token, 'invalid' = no match. */ status: 'valid' | 'duress' | 'invalid'; /** Identities of duress signallers (only when status = 'duress'). */ identities?: string[]; } /** Options for token verification. */ export interface VerifyOptions { /** Output encoding to use for comparison (default: single word). */ encoding?: TokenEncoding; /** Counter tolerance window: accept tokens within ±tolerance counter values (default: 0). */ tolerance?: number; } /** Options for estimating CANARY duress-aware online guessing surface. */ export interface CanaryVerificationRiskOptions { /** Output encoding to model (default: single word). */ encoding?: TokenEncoding; /** Counter tolerance window to model (default: 0). */ tolerance?: number; /** Identity count or identities array to model (default: 0). */ identities?: number | readonly string[]; /** Include anonymous group-wide fallback candidates (default: true). */ includeGroupFallback?: boolean; } /** Estimated online guessing surface for CANARY duress-aware verification. */ export interface CanaryVerificationRisk { /** Total accepted token candidates for one verification call. */ candidates: number; /** Anonymous group-wide normal-token candidates. */ groupCandidates: number; /** Per-identity normal-token candidates. */ normalIdentityCandidates: number; /** Per-identity duress-token candidates. */ duressCandidates: number; /** Number of possible values in the selected encoding. */ tokenSpace: number; /** Probability that one random input lands on any accepted candidate. */ singleAttemptSuccessProbability: number; /** Effective bits against one random online guess. */ effectiveBits: number; } /** * Estimate the accepted-token surface for CANARY's duress-aware verifier. * * This models the nominal full tolerance window. Near counter 0 or uint32 max, * runtime verification may accept fewer counters due to clamping. */ export declare function estimateCanaryVerificationRisk(options?: CanaryVerificationRiskOptions): CanaryVerificationRisk; /** * CANARY-DURESS: Verify a spoken/entered token against a group. * * Computes all candidate branches, then returns in safety-first priority: * 1. ALL identities' duress tokens (within tolerance window) → 'duress' with all matches * 2. Per-member normal token at exact counter → 'valid' * 3. Per-member normal token at remaining tolerance window → 'valid' * 4. Group-wide normal token within tolerance window → 'valid' * 5. No match → 'invalid' * * Group-wide normal tokens are retained as a backwards-compatibility fallback. * Duress wins over normal matches so that a coercion signal is never masked. * * Per CANARY-DURESS: the verifier MUST check all identities and collect all matches. * The verifier MUST NOT short-circuit after the first duress match. * * @param secret - Shared secret (hex string or Uint8Array). * @param context - Context string for domain separation. * @param counter - Current time-based counter. * @param input - The spoken/entered token to verify. * @param identities - Array of member pubkeys (max 100). * @param options - Optional encoding and tolerance settings. * @returns `{ status: 'valid' | 'duress' | 'invalid', identities?: string[] }`. * @throws {RangeError} If tolerance exceeds MAX_TOLERANCE or identities exceeds 100. * * @example * ```ts * const result = verifyToken(seed, 'canary:group', counter, 'falcon', [alice, bob]) * if (result.status === 'duress') alert(`Duress from: ${result.identities}`) * ``` */ export declare function verifyToken(secret: Uint8Array | string, context: string, counter: number, input: string, identities: string[], options?: VerifyOptions): TokenVerifyResult; /** * CANARY-DURESS: Derive a liveness heartbeat token for dead man's switch. * * Algorithm: HMAC-SHA256(secret, utf8(context + ":alive") || 0x00 || utf8(identity) || counter_be32) * * The null-byte separator between the context suffix and identity prevents concatenation * ambiguity. * * The liveness token proves both identity and knowledge of the secret. * If heartbeats stop arriving, the implementation triggers its DMS response. * * @param secret - Shared secret (hex string or Uint8Array, minimum 16 bytes). * @param context - Context string for domain separation (e.g. `'canary:group'`). * @param identity - Member pubkey or identifier of the heartbeat sender. * @param counter - Time-based or usage counter (uint32). * @returns Raw 32-byte HMAC-SHA256 digest for the liveness heartbeat. * @throws {RangeError} If secret is too short or counter is out of range. */ export declare function deriveLivenessToken(secret: Uint8Array | string, context: string, identity: string, counter: number): Uint8Array; //# sourceMappingURL=token.d.ts.map