OAraLabs/raven-core

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

README

raven-core

The cryptography and encoding core of Raven, a steganographic, metadata-resistant messenger. Portable TypeScript with no DOM, no framework, and no network calls.

Status

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.

Scope — what is deliberately not here

raven-core is the protocol core. It contains no I/O of any kind. It excludes:

  • The chain layer. No @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.
  • The relayer. Nothing here submits anything anywhere. There is no HTTP client.
  • The sweeper. Account lifecycle and rent reclamation live outside this package.
  • The client applications. No UI, no storage backend, no key management policy. StorageAdapter is an interface this package consumes; the chrome.storage.local and IndexedDB implementations are injected.

Cryptography

There are no custom primitives in this package. Every primitive comes from an established implementation; the code here is composition and encoding only.

PrimitiveProvided by
X25519 ECDH, Ed25519 sign/verifytweetnacl
Argon2id (vault key derivation)hash-wasm
AES-256-GCM, HKDF-SHA256, SHA-256Web 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.

Requirements

Node 20+. Consumed as TypeScript source: no build step, no dist/.

npm install

Tests

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

Interop fixtures

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.

Regenerating

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.

FixtureCommand
src/crypto/vault-kdf-fixture.jsonnpm run gen-vault-kdf-fixture
src/crypto/ephemeral-fixture.jsonnode scripts/gen-ephemeral-fixture.mjs
src/encoding/stealth-interop-fixture.jsonnpm run gen-stealth-interop-fixture
src/encoding/stealth-queryid-fixture.jsonnpm run gen-stealth-queryid-fixture
src/encoding/sprint17-5-encoding-fixture.json
src/encoding/sprint17-5-matchrule-fixture.json
npx tsx scripts/gen-sprint17-5-encoding-fixture.ts (writes both)
src/flock/frequency-fixture.jsonnpx tsx scripts/gen-flock-frequency-fixture.ts
src/keys/broadcast-carrier-filter-fixture.jsonnpm run gen-broadcast-carrier-filter-fixture
src/keys/channel-derivation-fixture.jsonnode scripts/gen-channel-fixture.mjs
src/keys/qr-share-fixture.jsonnpm run gen-qr-share-fixture
src/keys/sprint15-modela-fixture.jsonnode scripts/gen-sprint15-modela-fixture.mjs
src/keys/sprint17-interop-fixture.jsonnode scripts/gen-sprint17-interop-fixture.mjs
src/keys/stealth-shared-secret-fixture.jsonnpm run gen-stealth-shared-secret-fixture
src/scanning/private-carrier-gate-fixture.jsonnpm run gen-private-carrier-gate-fixture
scripts/demo-raven-fixture.jsonnpx 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.
  • Five fixtures have no generator and are maintained by hand, in lockstep with their Swift mirrors: 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.

Security

See SECURITY.md.

Further reading

  • Raven white paper — threat model, blob versions, PDA layout, stealth derivation, limitations.

License

Apache License 2.0. See LICENSE and NOTICE.

Contributors

OAraLabs

3 commits

OAraLabs/raven-core

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

README

raven-core

The cryptography and encoding core of Raven, a steganographic, metadata-resistant messenger. Portable TypeScript with no DOM, no framework, and no network calls.

Status

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.

Scope — what is deliberately not here

raven-core is the protocol core. It contains no I/O of any kind. It excludes:

  • The chain layer. No @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.
  • The relayer. Nothing here submits anything anywhere. There is no HTTP client.
  • The sweeper. Account lifecycle and rent reclamation live outside this package.
  • The client applications. No UI, no storage backend, no key management policy. StorageAdapter is an interface this package consumes; the chrome.storage.local and IndexedDB implementations are injected.

Cryptography

There are no custom primitives in this package. Every primitive comes from an established implementation; the code here is composition and encoding only.

PrimitiveProvided by
X25519 ECDH, Ed25519 sign/verifytweetnacl
Argon2id (vault key derivation)hash-wasm
AES-256-GCM, HKDF-SHA256, SHA-256Web 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.

Requirements

Node 20+. Consumed as TypeScript source: no build step, no dist/.

npm install

Tests

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

Interop fixtures

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.

Regenerating

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.

FixtureCommand
src/crypto/vault-kdf-fixture.jsonnpm run gen-vault-kdf-fixture
src/crypto/ephemeral-fixture.jsonnode scripts/gen-ephemeral-fixture.mjs
src/encoding/stealth-interop-fixture.jsonnpm run gen-stealth-interop-fixture
src/encoding/stealth-queryid-fixture.jsonnpm run gen-stealth-queryid-fixture
src/encoding/sprint17-5-encoding-fixture.json
src/encoding/sprint17-5-matchrule-fixture.json
npx tsx scripts/gen-sprint17-5-encoding-fixture.ts (writes both)
src/flock/frequency-fixture.jsonnpx tsx scripts/gen-flock-frequency-fixture.ts
src/keys/broadcast-carrier-filter-fixture.jsonnpm run gen-broadcast-carrier-filter-fixture
src/keys/channel-derivation-fixture.jsonnode scripts/gen-channel-fixture.mjs
src/keys/qr-share-fixture.jsonnpm run gen-qr-share-fixture
src/keys/sprint15-modela-fixture.jsonnode scripts/gen-sprint15-modela-fixture.mjs
src/keys/sprint17-interop-fixture.jsonnode scripts/gen-sprint17-interop-fixture.mjs
src/keys/stealth-shared-secret-fixture.jsonnpm run gen-stealth-shared-secret-fixture
src/scanning/private-carrier-gate-fixture.jsonnpm run gen-private-carrier-gate-fixture
scripts/demo-raven-fixture.jsonnpx 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.
  • Five fixtures have no generator and are maintained by hand, in lockstep with their Swift mirrors: 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.

Security

See SECURITY.md.

Further reading

  • Raven white paper — threat model, blob versions, PDA layout, stealth derivation, limitations.

License

Apache License 2.0. See LICENSE and NOTICE.

Contributors

OAraLabs

3 commits

Languages

TypeScript

93.6%

JavaScript

6.4%