{"id":47595576,"url":"https://github.com/forgesworn/canary-kit","last_synced_at":"2026-04-01T18:02:49.258Z","repository":{"id":344851267,"uuid":"1171089390","full_name":"forgesworn/canary-kit","owner":"forgesworn","description":"Deepfake-proof identity verification. Per-member spoken words, silent duress detection, encrypted group sync. Open protocol.","archived":false,"fork":false,"pushed_at":"2026-03-25T10:51:33.000Z","size":7236,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-26T04:12:34.082Z","etag":null,"topics":["cryptography","deepfake-detection","duress-detection","identity-verification","minimal-dependencies","nostr","open-protocol","pwa","security","typescript"],"latest_commit_sha":null,"homepage":"https://canary.trotters.cc","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/forgesworn.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":"THREAT-MODEL.md","audit":"AUDIT.md","citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"custom":["https://strike.me/thedonkey"]}},"created_at":"2026-03-02T21:31:33.000Z","updated_at":"2026-03-25T10:51:52.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/forgesworn/canary-kit","commit_stats":null,"previous_names":["thecryptodonkey/canary-kit","forgesworn/canary-kit"],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/forgesworn/canary-kit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forgesworn%2Fcanary-kit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forgesworn%2Fcanary-kit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forgesworn%2Fcanary-kit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forgesworn%2Fcanary-kit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/forgesworn","download_url":"https://codeload.github.com/forgesworn/canary-kit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forgesworn%2Fcanary-kit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31290741,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cryptography","deepfake-detection","duress-detection","identity-verification","minimal-dependencies","nostr","open-protocol","pwa","security","typescript"],"created_at":"2026-04-01T18:02:44.250Z","updated_at":"2026-04-01T18:02:49.250Z","avatar_url":"https://github.com/forgesworn.png","language":"TypeScript","funding_links":["https://strike.me/thedonkey"],"categories":[],"sub_categories":[],"readme":"# canary-kit\n\n**Nostr:** [`npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2`](https://njump.me/npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2)\n\n\u003e Deepfake-proof identity verification. Open protocol, minimal dependencies.\n\n[![npm](https://img.shields.io/npm/v/canary-kit)](https://www.npmjs.com/package/canary-kit)\n[![CI](https://github.com/forgesworn/canary-kit/actions/workflows/ci.yml/badge.svg)](https://github.com/forgesworn/canary-kit/actions)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n[![TypeScript](https://img.shields.io/badge/TypeScript-native-blue)](https://www.typescriptlang.org/)\n[![Coverage](https://img.shields.io/badge/coverage-95%25-brightgreen)](vitest.config.ts)\n\n**[Interactive Demo](https://canary.trotters.cc/)** · [Protocol Spec](CANARY.md) · [Nostr Binding](NIP-CANARY.md) · [Integration Guide](INTEGRATION.md) · [Groups Protocol](GROUPS.md) · [Nostr Transport](NIP-XX.md) · [Threat Model](THREAT-MODEL.md) · [Regulatory](REGULATORY.md)\n\n## Why Now\n\nRegulators and criminals arrived at the same inflection point simultaneously. In\nMarch 2023 the UN Office on Drugs and Crime formally linked AI synthetic voice to\norganised criminal networks operating cross-border fraud at institutional scale.\nVoice cloning tools are now available as a service for under $400/month; vishing\nsurged 442% in 2025. The same week, the UAE Central Bank set a 31 March 2026\ndeadline banning SMS OTP across all licensed financial institutions — the first\nnational regulator to mandate its replacement. India's RBI follows on 1 April 2026\nwith mandatory two-factor authentication for all digital payment transactions. The\nEU AI Act's deepfake transparency obligation (Article 50) takes effect in August\n2026; EUDI Wallets must be available across all 27 Member States by December 2026.\nFCA Strong Customer Authentication technical standards were updated in March 2026.\n\nCANARY is positioned where these pressures converge: the voice channel, where\nauthentication is weakest and the regulatory gap is largest. For a detailed mapping\nof CANARY's security properties against each regulation, see\n[REGULATORY.md](REGULATORY.md).\n\nThe full verification stack covers four caller scenarios: known person, known\ninstitution (CANARY handles this), unknown person, and unknown institution\ncold-calling — the last via [Signet](https://github.com/forgesworn/signet)\ncold-call verification (forthcoming). Deepfake labelling tools and CANARY are\ncomplementary: one labels AI-generated content after the fact; CANARY verifies\nthe caller's identity in real time at the point of interaction.\n\n## The Problem\n\nVoice phishing surged 442% in 2025. AI can clone a voice from three seconds of\naudio. The tools that were supposed to protect us are failing:\n\n- **Security questions** are one-directional and socially engineerable\n- **Voice biometrics** — 91% of US banks are reconsidering after deepfake attacks\n- **TOTP codes** prove you to a server, but never prove the server to you\n- **\"Family safe words\"** are static, never rotate, and have no duress signalling\n\nCANARY is the first protocol that combines **bidirectional verification** (both\nsides prove identity), **coercion resistance** (duress tokens), and **spoken-word\noutput** — three properties that have never existed together in a standard.\n\nIt works because cloning a voice doesn't help you derive the right word. Only\nknowledge of the shared secret does.\n\n## Quick Start\n\n```bash\nnpm install canary-kit\n```\n\n### Phone Verification (Insurance, Banking)\n\n```typescript\nimport { createSession } from 'canary-kit/session'\n\nconst session = createSession({\n  secret: sharedSeed,\n  namespace: 'aviva',\n  roles: ['caller', 'agent'],\n  myRole: 'agent',\n  preset: 'call',\n})\n\nsession.myToken()        // \"choose\" — what I speak\nsession.theirToken()     // \"bid\" — what I expect to hear\nsession.verify('bid')    // { status: 'valid' }\n```\n\n### Family / Team Verification\n\n```typescript\nimport { createGroup, getCurrentWord, verifyWord, getCounter } from 'canary-kit'\n\nconst group = createGroup({\n  name: 'Family',\n  members: [alicePubkey, bobPubkey],\n  preset: 'family',\n})\n\ngetCurrentWord(group)  // \"falcon\"\n```\n\n## Use Cases\n\n| Use case | Preset | Rotation | What it replaces |\n|----------|--------|----------|------------------|\n| Insurance phone calls | `call` | 30 seconds | Security questions |\n| Banking phone calls | `call` | 30 seconds | Voice biometrics, callbacks |\n| Rideshare/delivery handoff | `handoff` | Single-use | Random PINs |\n| Family safety | `family` | 7 days | Static safe words |\n| Journalism / activism | `field-ops` | 24 hours | Nothing (no existing standard) |\n| Enterprise incident response | `enterprise` | 48 hours | Challenge-response over email |\n\n## Why Not Just...\n\n| Solution | Limitation CANARY solves |\n|----------|------------------------|\n| Security questions | One-directional. Socially engineerable. No rotation. |\n| Voice biometrics | Defeated by AI voice cloning. One-directional. |\n| TOTP (Google Auth) | Machine-readable digits, not spoken words. No duress. One-directional. |\n| Callback numbers | Slow. Doesn't prove the agent's identity. |\n| BIP-39 wordlist | No verification protocol. No rotation. No duress. |\n| \"Family safe word\" | Static. No rotation. No duress. No protocol. |\n| **CANARY** | **Bidirectional. Deepfake-proof. Duress-aware. Rotating. Offline. Open.** |\n\n## Why Canary\n\n**Bidirectional.** Both sides prove identity. The caller proves they know the secret, and the agent proves it back. Neither can impersonate the other.\n\n**Built on proven primitives.** CANARY extends the HMAC-counter pattern from HOTP (RFC 4226) and TOTP (RFC 6238) to human-to-human spoken verification, adding duress signalling and coercion resistance.\n\n**Offline-first.** Words are derived locally from a shared seed and a time-based counter. No network is required after initial setup.\n\n**Duress-aware.** Every party has a personal duress word distinct from the verification word. Speaking it silently alerts the system while giving the attacker plausible deniability.\n\n**Automatic rotation.** Configurable intervals — 30 seconds for phone calls, 7 days for family groups.\n\n**Minimal dependencies.** Core crypto is pure JavaScript. Only `@scure/bip32` and `@scure/bip39` for mnemonic key recovery. Requires `globalThis.crypto` (Web Crypto API): all browsers, Node.js 22+, Deno, and edge runtimes.\n\n**Protocol-grade.** Formal specification with published test vectors and a curated 2048-word spoken-clarity wordlist.\n\n## Compatibility\n\n| Runtime | Version | Notes |\n|---------|---------|-------|\n| Node.js | 22+ | Full support (`globalThis.crypto` required) |\n| Deno | 1.x+ | Full support |\n| Bun | 1.x+ | Full support |\n| Browsers | All modern | Chrome, Firefox, Safari, Edge |\n| Cloudflare Workers | Yes | Web Crypto API available |\n| React Native | Via polyfill | Needs `crypto.subtle` polyfill |\n\nESM-only. Eight subpath exports for tree-shaking:\n\n```typescript\nimport { createSession } from 'canary-kit/session'    // just sessions\nimport { deriveToken } from 'canary-kit/token'         // just derivation\nimport { encodeAsWords } from 'canary-kit/encoding'    // just encoding\nimport { WORDLIST } from 'canary-kit/wordlist'          // just the wordlist\nimport { buildGroupStateEvent } from 'canary-kit/nostr' // just Nostr\nimport { encryptBeacon } from 'canary-kit/beacon'      // just beacons\nimport { applySyncMessage } from 'canary-kit/sync'     // just sync protocol\n```\n\n## Security\n\n- **Minimal runtime dependencies** — only `@scure/bip32` and `@scure/bip39` for mnemonic key recovery; core crypto is pure JS\n- **Automated publishing** — GitHub Actions with OIDC trusted publishing, no stored tokens\n- **Provenance signed** — npm provenance attestation enabled\n- **Protocol-grade test vectors** — frozen canonical vectors in both CANARY.md and NIP-CANARY.md; any conformant implementation must produce identical results\n- **Timing-safe byte compare** — `timingSafeEqual()` utility provided for constant-time byte operations\n- **Bounded tolerance** — `MAX_TOLERANCE` cap prevents pathological iteration\n\nSee [SECURITY.md](SECURITY.md) for vulnerability disclosure and known limitations. See [CANARY.md](CANARY.md) for the full security analysis.\n\n## API\n\n| Subpath export | Key functions |\n|---|---|\n| `canary-kit/session` | `createSession`, `generateSeed`, `deriveSeed` |\n| `canary-kit/token` | `deriveToken`, `verifyToken`, `deriveDuressToken`, `deriveLivenessToken` |\n| `canary-kit/encoding` | `encodeAsWords`, `encodeAsPin`, `encodeAsHex` |\n| `canary-kit` | `createGroup`, `getCurrentWord`, `verifyWord`, `addMember`, `reseed` |\n| `canary-kit/nostr` | `buildGroupStateEvent`, `buildSignalEvent`, `buildStoredSignalEvent`, `buildRumourEvent` |\n| `canary-kit/beacon` | `encryptBeacon`, `decryptBeacon`, `buildDuressAlert` |\n| `canary-kit/sync` | `applySyncMessage`, `encodeSyncMessage`, `deriveGroupKey` |\n| `canary-kit/wordlist` | `WORDLIST`, `getWord`, `indexOf` |\n\nFull API documentation with signatures, types, and presets: **[API.md](API.md)**\n\n## Protocol\n\nThe full protocol specification is in [CANARY.md](CANARY.md). The Nostr binding is in [NIP-CANARY.md](NIP-CANARY.md). The integration guide for finance/enterprise is in [INTEGRATION.md](INTEGRATION.md).\n\n| Event | Kind | Type |\n|---|---|---|\n| Group state / stored signals | `30078` | Parameterised replaceable |\n| Real-time signals | `20078` | Ephemeral |\n| Seed distribution / member updates | `14` → `1059` | NIP-17 gift wrap (kind 14 rumour sealed + wrapped) |\n\nContent is encrypted with **NIP-44**. Group state events use the `ssg/` d-tag namespace. Seed distribution and member updates use **NIP-17** gift wrapping (kind 14 rumour → kind 13 seal → kind 1059 gift wrap). Events may carry a **NIP-40** `expiration` tag.\n\n## For AI Assistants\n\n- [llms.txt](llms.txt) — concise API summary\n- [llms-full.txt](llms-full.txt) — complete reference with all type signatures\n\n## Support\n\nFor issues and feature requests, see [GitHub Issues](https://github.com/forgesworn/canary-kit/issues).\n\nIf you find canary-kit useful, consider sending a tip:\n\n- **Lightning:** `thedonkey@strike.me`\n- **Nostr zaps:** `npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2`\n\n## Licence\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fforgesworn%2Fcanary-kit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fforgesworn%2Fcanary-kit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fforgesworn%2Fcanary-kit/lists"}