Cryptography and steganographic encoding core for Raven: X25519 ECDH, HKDF-SHA256, AES-256-GCM, Ed25519 signing, Argon2id vault sealing, and carrier-text encoding rules. Deliberately excludes the chain, relayer, and client layers.
0
stars
3
commits
TypeScript
primary language
Sep 5, 2026
updated
The cryptography and encoding core of Raven, a steganographic, metadata-resistant messenger. Portable TypeScript with no DOM, no framework, and no network calls.
Maintained by one person. Issues and pull requests may sit. The protocol is stable as of the published fixtures: the wire formats and derivations they pin are not expected to change. The library API is not stable and may change between versions.
raven-core is the protocol core. It contains no I/O of any kind. It excludes:
@solana/web3.js at runtime, no RPC client, no transaction building, no
program interaction. Where an on-chain address is involved, raven-core returns the seed bytes
and the caller derives the address with its own Solana client. @solana/web3.js is a
devDependency, used by three test files to check derived seeds against real PDA math.StorageAdapter
is an interface this package consumes; the chrome.storage.local and IndexedDB implementations
are injected.There are no custom primitives in this package. Every primitive comes from an established implementation; the code here is composition and encoding only.
| Primitive | Provided by |
|---|---|
| X25519 ECDH, Ed25519 sign/verify | tweetnacl |
| Argon2id (vault key derivation) | hash-wasm |
| AES-256-GCM, HKDF-SHA256, SHA-256 | Web Crypto (crypto.subtle), host-provided |
| Passphrase strength estimation | @zxcvbn-ts |
Composition: X25519 ECDH → HKDF-SHA256 (info "raven-v1") → AES-256-GCM. Public broadcasts add an
Ed25519 signature over a canonical JSON encoding. The vault is an Argon2id-derived AES-256-GCM
envelope.
Node 20+. Consumed as TypeScript source: no build step, no dist/.
npm install
npm test
Runs every *.test.ts under src/ through tsx --test. The suite is offline: no network, no
fixtures fetched at runtime.
Type-check:
npx tsc --noEmit
Single file:
npx tsx --test src/crypto/encrypt.test.ts
Files under src/**/ named *-fixture.json are published test vectors. Each pins the exact bytes a
conforming implementation must produce for a set of inputs: derived keys, canonical encodings,
HKDF outputs, PDA seeds, ciphertexts.
raven-ios is an independent Swift implementation of the same protocol, written against CryptoKit
rather than tweetnacl. It is not a port of this code. Both implementations consume the same fixture
files: this package's tests read them from src/, and the Swift test target reads a byte-identical
mirror. The iOS source is not public; these vectors are sufficient on their own to check any
implementation.
Key material in these fixtures is synthetic. Every fixture except qr-share-fixture.json is derived
from pinned, visibly patterned seeds (a1a1a1…, b0b0b0…, c0ffee…); qr-share-fixture.json
carries freshly generated throwaway keys. None corresponds to a real account, vault, or message.
Most generators write the raven-core copy and, when a sibling raven-ios checkout is present, its
mirror in the same run. RAVEN_IOS_REPO points at that checkout; when it is absent the mirror write
is skipped with a warning and the raven-core copy is still written.
| Fixture | Command |
|---|---|
src/crypto/vault-kdf-fixture.json | npm run gen-vault-kdf-fixture |
src/crypto/ephemeral-fixture.json | node scripts/gen-ephemeral-fixture.mjs |
src/encoding/stealth-interop-fixture.json | npm run gen-stealth-interop-fixture |
src/encoding/stealth-queryid-fixture.json | npm run gen-stealth-queryid-fixture |
src/encoding/sprint17-5-encoding-fixture.jsonsrc/encoding/sprint17-5-matchrule-fixture.json | npx tsx scripts/gen-sprint17-5-encoding-fixture.ts (writes both) |
src/flock/frequency-fixture.json | npx tsx scripts/gen-flock-frequency-fixture.ts |
src/keys/broadcast-carrier-filter-fixture.json | npm run gen-broadcast-carrier-filter-fixture |
src/keys/channel-derivation-fixture.json | node scripts/gen-channel-fixture.mjs |
src/keys/qr-share-fixture.json | npm run gen-qr-share-fixture |
src/keys/sprint15-modela-fixture.json | node scripts/gen-sprint15-modela-fixture.mjs |
src/keys/sprint17-interop-fixture.json | node scripts/gen-sprint17-interop-fixture.mjs |
src/keys/stealth-shared-secret-fixture.json | npm run gen-stealth-shared-secret-fixture |
src/scanning/private-carrier-gate-fixture.json | npm run gen-private-carrier-gate-fixture |
scripts/demo-raven-fixture.json | npx tsx scripts/gen-demo-fixture.ts |
qr-share-fixture.json is not reproducible. Its generator calls the production key serializers,
which mint a fresh identity, fresh UUIDs, and a Date.now() timestamp on every call. Regeneration
produces different but equally valid bytes. Every other fixture in the table is deterministic from
pinned seeds.src/reveal/inbound-indicator-state-fixture.json, src/reveal/reveal-hold-state-fixture.json,
src/scanning/cooldown-fixture.json, src/scanning/safety-net-fixture.json,
src/security/idle-lock-fixture.json. They pin state machines and constants.See SECURITY.md.
3 commits
TypeScript
93.6%
JavaScript
6.4%
Cryptography and steganographic encoding core for Raven: X25519 ECDH, HKDF-SHA256, AES-256-GCM, Ed25519 signing, Argon2id vault sealing, and carrier-text encoding rules. Deliberately excludes the chain, relayer, and client layers.
0
stars
3
commits
TypeScript
primary language
Sep 5, 2026
updated
The cryptography and encoding core of Raven, a steganographic, metadata-resistant messenger. Portable TypeScript with no DOM, no framework, and no network calls.
Maintained by one person. Issues and pull requests may sit. The protocol is stable as of the published fixtures: the wire formats and derivations they pin are not expected to change. The library API is not stable and may change between versions.
raven-core is the protocol core. It contains no I/O of any kind. It excludes:
@solana/web3.js at runtime, no RPC client, no transaction building, no
program interaction. Where an on-chain address is involved, raven-core returns the seed bytes
and the caller derives the address with its own Solana client. @solana/web3.js is a
devDependency, used by three test files to check derived seeds against real PDA math.StorageAdapter
is an interface this package consumes; the chrome.storage.local and IndexedDB implementations
are injected.There are no custom primitives in this package. Every primitive comes from an established implementation; the code here is composition and encoding only.
| Primitive | Provided by |
|---|---|
| X25519 ECDH, Ed25519 sign/verify | tweetnacl |
| Argon2id (vault key derivation) | hash-wasm |
| AES-256-GCM, HKDF-SHA256, SHA-256 | Web Crypto (crypto.subtle), host-provided |
| Passphrase strength estimation | @zxcvbn-ts |
Composition: X25519 ECDH → HKDF-SHA256 (info "raven-v1") → AES-256-GCM. Public broadcasts add an
Ed25519 signature over a canonical JSON encoding. The vault is an Argon2id-derived AES-256-GCM
envelope.
Node 20+. Consumed as TypeScript source: no build step, no dist/.
npm install
npm test
Runs every *.test.ts under src/ through tsx --test. The suite is offline: no network, no
fixtures fetched at runtime.
Type-check:
npx tsc --noEmit
Single file:
npx tsx --test src/crypto/encrypt.test.ts
Files under src/**/ named *-fixture.json are published test vectors. Each pins the exact bytes a
conforming implementation must produce for a set of inputs: derived keys, canonical encodings,
HKDF outputs, PDA seeds, ciphertexts.
raven-ios is an independent Swift implementation of the same protocol, written against CryptoKit
rather than tweetnacl. It is not a port of this code. Both implementations consume the same fixture
files: this package's tests read them from src/, and the Swift test target reads a byte-identical
mirror. The iOS source is not public; these vectors are sufficient on their own to check any
implementation.
Key material in these fixtures is synthetic. Every fixture except qr-share-fixture.json is derived
from pinned, visibly patterned seeds (a1a1a1…, b0b0b0…, c0ffee…); qr-share-fixture.json
carries freshly generated throwaway keys. None corresponds to a real account, vault, or message.
Most generators write the raven-core copy and, when a sibling raven-ios checkout is present, its
mirror in the same run. RAVEN_IOS_REPO points at that checkout; when it is absent the mirror write
is skipped with a warning and the raven-core copy is still written.
| Fixture | Command |
|---|---|
src/crypto/vault-kdf-fixture.json | npm run gen-vault-kdf-fixture |
src/crypto/ephemeral-fixture.json | node scripts/gen-ephemeral-fixture.mjs |
src/encoding/stealth-interop-fixture.json | npm run gen-stealth-interop-fixture |
src/encoding/stealth-queryid-fixture.json | npm run gen-stealth-queryid-fixture |
src/encoding/sprint17-5-encoding-fixture.jsonsrc/encoding/sprint17-5-matchrule-fixture.json | npx tsx scripts/gen-sprint17-5-encoding-fixture.ts (writes both) |
src/flock/frequency-fixture.json | npx tsx scripts/gen-flock-frequency-fixture.ts |
src/keys/broadcast-carrier-filter-fixture.json | npm run gen-broadcast-carrier-filter-fixture |
src/keys/channel-derivation-fixture.json | node scripts/gen-channel-fixture.mjs |
src/keys/qr-share-fixture.json | npm run gen-qr-share-fixture |
src/keys/sprint15-modela-fixture.json | node scripts/gen-sprint15-modela-fixture.mjs |
src/keys/sprint17-interop-fixture.json | node scripts/gen-sprint17-interop-fixture.mjs |
src/keys/stealth-shared-secret-fixture.json | npm run gen-stealth-shared-secret-fixture |
src/scanning/private-carrier-gate-fixture.json | npm run gen-private-carrier-gate-fixture |
scripts/demo-raven-fixture.json | npx tsx scripts/gen-demo-fixture.ts |
qr-share-fixture.json is not reproducible. Its generator calls the production key serializers,
which mint a fresh identity, fresh UUIDs, and a Date.now() timestamp on every call. Regeneration
produces different but equally valid bytes. Every other fixture in the table is deterministic from
pinned seeds.src/reveal/inbound-indicator-state-fixture.json, src/reveal/reveal-hold-state-fixture.json,
src/scanning/cooldown-fixture.json, src/scanning/safety-net-fixture.json,
src/security/idle-lock-fixture.json. They pin state machines and constants.See SECURITY.md.
3 commits
TypeScript
93.6%
JavaScript
6.4%