OMEGA Protocol: Auditing and Hardening
GitHub RepositoryComplete audit cycle of Protocol OMEGA, from adversary definition to post-remediation verification. Four findings directly contradicted the "zero-trust relay" claim in the README. The audit produced 21 findings total; 20 were remediated and verified, and 1 (post-quantum migration) remains in roadmap. This walkthrough covers the reasoning at each stage so the methodology transfers to other E2EE systems.
1. Threat Modeling
// 1.1 Why the threat model comes first
The README asserts two properties: "relay blindness" and "zero-knowledge." Neither is meaningful until you specify the adversary. A vulnerability finding is only actionable relative to a concrete attacker with concrete capabilities. Auditing against "everything possible" produces a report of unsorted paranoia instead of a prioritized remediation list. So before reading a line of crypto code, the adversary was fixed in writing.
// 1.2 Adversary capabilities
The adversary model used is an Extended Dolev-Yao model — an active and passive adversary with network control, not a passive eavesdropper. Four concrete parameters:
| Capability | Parameter | Implication |
|---|---|---|
| Network control | Active control of up to 30% of overlay nodes (Tor) | Can observe circuits, replay frames, and correlate traffic across the network |
| Traffic analysis | IAT (Inter-Arrival Time) classifiers based on Transformer architecture | Can distinguish real sessions from noise padding by timing patterns |
| Indefinite capture | Mass storage under Harvest-Now-Decrypt-Later | Records ciphertext today on the assumption it can be decrypted later |
| Quantum capability | Polynomial-time discrete log / integer factorization (CRQC) | Breaks ECDH P-256 and RSA-4096 retrospectively |
The 30% figure is not arbitrary: it is the standard threshold used in onion-routing anonymity research to model an adversary who can plausibly compromise a meaningful fraction of a circuit's nodes.
// 1.3 Deployment scenarios
The same codebase has different security properties depending on where it runs. This matters because it changes what a finding actually means:
.onion maps to whatever host runs the relay; it adds transport anonymity but does not change the host's trust level.The "zero-trust" claim only holds under (a) with a benign operator. This is stated explicitly up front so the findings are not misread as applying uniformly to all three deployments.
// 1.4 Exclusions
| Exclusion | Reason |
|---|---|
| Kernel-level malware on endpoints | Standard assumption in protocol analysis. Without it, every system is trivially broken by keylogging or memory scraping |
| Host compromise before the operator's first session | Inherent to self-hosting. The defense is a strong passphrase plus encrypted key material at rest |
| Quantum computers in production today | Not operationally real yet, but HNDL means the migration must be planned, not deferred indefinitely |
These are stated so the reader can assess whether the audit's scope matches their own threat model.
2. Whitebox Static Analysis
// 2.1 Reading the code
Static analysis gives full visibility into the code, which can obscure architectural defects behind an apparent completeness. Three systematic checks were applied:
// 2.2 H2 — Admin code served without integrity check
The admin panel is a web page served by the same relay that hosts the chat. The entry point:
<!-- src/admin.html, line 170 -->
<script src="admin-client.js"></script> The <script> tag has no integrity attribute. There is no Subresource Integrity (SRI) hash binding admin-client.js to a value the browser trusts.
The project has an integrity mechanism, but it is incomplete and circular. GOLD_HASH.txt stores a SHA-512 hash, but it covers only omega-worker.js — the crypto worker — not the admin UI. Worse, the client fetches that hash from the same relay it is supposed to be verifying. The relay is both the thing being verified and the source of the verification data. This is a circular trust anchor.
Attack
Replace admin-client.js on the relay with a version that, on load, exfiltrates the passphrase and the RSA private key the operator enters in the panel. The attacker now holds the operator's long-term identity. Because that key authenticates the operator to the relay and decrypts the INIT payloads containing session tokens, the attacker can read every session.
Why static analysis is where this surfaces. The crypto primitives (RSA-PSS, AES-GCM) are correct. The defect is in the supply chain: a relay should not serve the code that is used to verify the relay's claims.
// 2.3 H3 — ECDH keys are not authenticated
Client and operator agree on ephemeral ECDH keys at the start of a session. These keys are supposed to prove the other party's identity:
// client.js
const pubKey = frame.publicKey; // sent by the server
// used directly to compute the shared secret
// never verified against the operator's long-term key The key arrives on the wire without a signature, a fingerprint, or a nonce binding it to the session. There is no Trust-On-First-Use (TOFU) step: no fingerprint is displayed, nothing for the user to confirm manually.
Attack
A relay controlling the transport intercepts the client's ECDH public key and the operator's, and substitutes its own key on each side. It computes the shared secret with the client using one key and with the operator using the other. Both sides believe they are talking to the legitimate peer. The relay decrypts the session. Participants see normal traffic with no error.
Severity framing. The attack is a silent MITM: it produces no failure and no warning. That is what makes it high severity — not just that it is possible, but that it is undetectable by design.
// 2.4 Rating findings in context
Severity is not a property of the code alone. It depends on exploitability, impact, and the deployment context.
Example — H1: server_secrets.enc in plaintext. server_secrets.enc stores the admin HMAC secret in plaintext JSON. In isolation that reads as HIGH. In context:
The finding is downgraded to MEDIUM. It is still a defect — secrets should not sit on disk in plaintext — but it does not, on its own, elevate the attacker's capability in any realistic scenario.
3. Verification in Live Traffic
// 3.1 Why blackbox
Static analysis states what the code claims. Live capture states what the server actually does. When the two disagree, that discrepancy is data: it reveals undocumented code paths, environment-specific behavior, or mitigations that live outside the code (a reverse proxy, a WAF, a TLS termination point). Static and blackbox are both incomplete; only comparing them is complete.
// 3.2 Lab setup
Separate machines, not localhost, so the relay is observed as a remote service over the actual network path, not through the loopback interface where behavior can differ. Capture was passive: download assets, observe WebSocket frames, and cross-check against the code. No frames were modified and no session was actively hijacked during capture.
// 3.3 H2 confirmed in traffic
The admin assets were downloaded and hashed:
GOLD_HASH.txt (server): d794bcc6bc37ebe593cd2c0f366da52b...
omega-worker.js (actual): d794bcc6bc37ebe593cd2c0f366da52b... # match
admin-client.js (actual): 7f0e0fb783... # NOT covered by GOLD_HASH admin.html on the wire carried no integrity attribute. The static analysis conclusion holds on the live service: the admin UI is served without a verifiable integrity anchor, and the only existing hash does not cover it.
// 3.4 H3 confirmed in traffic
The server's ECDH_EXCHANGE frame, captured from the wire:
{"type":"ECDH_EXCHANGE","publicKey":"1c64c6e3...","signature":null} The public key travels unsigned. A grep of the client bundle for crypto.subtle.verify finds it only in the ADMIN_AUTH path — never in the ECDH handshake. There is no code path that authenticates the key before the shared secret is derived.
// 3.5 M4 — Session hijacking confirmed
A random, never-registered sessionId was sent in a handshake:
{"type":"HANDSHAKE","sessionId":"3ecc60724c654fc039b98ec38e8044ca"}
> {"type":"HANDSHAKE_ACK"} No cookie, no token, no proof of possession, no binding of the session identifier to any key. The sessionId is a self-declared value.
Attack
An attacker who observes a real sessionId — via clearnet sniffing in a non-Tor deployment, or via a 30% Tor guard position that lets them correlate a circuit — registers that sessionId, substitutes their own ECDH key, and reads all future messages addressed to that session.
4. Root Cause
The design goal was a stateless relay: clients and operator share the same protocol code, and the relay simply forwards ciphertext. The implicit design shortcut was to authenticate nothing and rely on encryption alone — the reasoning being "if the relay cannot read the ciphertext, it does not matter whether it is trusted."
That reasoning is wrong at one specific point: a compromised relay substitutes code and keys before the ciphertext is produced. Integrity and authenticity must be established before encryption begins, and they cannot be delegated to the entity being authenticated.
The contradiction is then visible: the README declares a zero-trust relay, but the implementation assumes a trusted operator. Zero-trust means no assumptions; this code assumes control of the host.
5. Remediation
// 5.1 Admin panel integrity (H2) — five layers
A single verification layer would be a single point of failure. The fix layers five independent controls; an attacker must break all five, not one.
Layer 1 — Content Security Policy
The admin page is served with a strict CSP that forbids inline scripts and eval:
Content-Security-Policy: default-src 'none';
script-src 'self' blob:;
connect-src 'self' ws: wss:;
style-src 'self';
base-uri 'none'; form-action 'none'; frame-ancestors 'none' This blocks script injection through any XSS path, and removes the 'unsafe-inline'/'unsafe-eval' that previously broadened the script surface.
Layer 2 — Subresource Integrity
admin.html pins the SHA-512 hash of admin-client.js in the integrity attribute, injected at build time:
<script src="admin-client.js"
integrity="sha512-__HASH_ADMIN_CLIENT__"
crossorigin="anonymous"></script> The browser refuses to execute a script whose hash does not match. Swapping admin-client.js alone is now rejected automatically, with no operator interaction.
Layer 3 — Service Worker pin
The first visit (over a trusted channel) installs a Service Worker that caches and pins the hash of every admin asset — including admin.html itself:
// admin-sw.js
const PINNED = {
'admin.html': 'sha512-__HASH_HTML__',
'admin-client.js': 'sha512-__HASH_CLIENT__',
'master_public.pem': 'sha512-__HASH_PEM__'
};
self.addEventListener('fetch', e => {
const name = new URL(e.request.url).pathname.split('/').pop();
if (!PINNED[name]) return;
e.respondWith((async () => {
const resp = await fetch(e.request);
const buf = await resp.arrayBuffer();
const digest = await crypto.subtle.digest('SHA-512', buf);
const hex = [...new Uint8Array(digest)].map(b => b.toString(16).padStart(2,'0')).join('');
if (hex !== PINNED[name].replace(/^sha512-/, '')) {
return new Response('INTEGRITY FAILURE', { status: 500 });
}
return new Response(buf, resp);
})());
}); Once pinned, any later alteration of the admin assets — including a full rewrite of admin.html — is detected and blocked. This closes the gap left by SRI, which protects a single script but not the HTML that loads it.
Layer 4 — Separate directory and route
Admin assets move to /admin/, outside the express.static directory that serves the client UI. admin.html is served only through the HMAC token route, not as a static file:
app.get('/:token', (req, res, next) => {
if (isValidAdminPath(req.params.token))
return res.sendFile(path.join(__dirname, '../admin/admin.html'));
next();
}); This removes the L1 finding (admin reachable as a public static path) and removes GOLD_HASH.txt from the served tree.
Layer 5 — Out-of-band hashes
The build prints the SHA-512 of every asset to the console instead of writing them to a served file. The operator archives these offline and verifies before using the panel. This gives a manual anchor that exists entirely outside the relay's control.
An attacker must defeat CSP, SRI, the Service Worker pin, the route separation, and the operator's offline record simultaneously. Breaking any single layer is insufficient.
// 5.2 Sign the ECDH key (H3)
The operator signs their ephemeral ECDH public key with their long-term RSA private key, using a domain-separated string that binds the key to the session:
// Admin's browser
signature = RSA_PSS_sign('OMEGA_ECDH:' + sessionId + ':' + publicKeyHex, masterPrivateKey);
// Client side, before deriving the shared secret
ok = RSA_PSS_verify(masterPublicKey, signature, 'OMEGA_ECDH:' + sessionId + ':' + publicKey);
if (!ok) throw 'ECDH_AUTH_FAIL'; The domain prefix OMEGA_ECDH: prevents the signature from being reused in another protocol context that shares the same long-term key. Two properties follow:
sessionId component of the signed string.The relay does not need to understand the signature — it only forwards it as opaque bytes.
// 5.3 Bind sessionId to the ECDH key (M4)
The session identifier is bound to the client's ECDH public key by a fingerprint:
fp = SHA256(clientEcdhPublicKey);
sessionEcdhFp.set(sessionId, fp); On a second registration of the same sessionId with a different key, the server rejects it:
const prior = sessionEcdhFp.get(sessionId);
if (prior && prior !== fp) return ws.close(1008, 'SESSION_KEY_MISMATCH');
sessionEcdhFp.set(sessionId, fp); Once a session is bound, its ECDH key is locked. Substitution and hijacking both fail.
6. Report Structure
// 6.1 Sections
The final report followed six sections so each finding is auditable end to end:
// 6.2 Severity calibration — the M5 example
M5 (vault write amplification) was first written as "500 writes per second, the vault file is rewritten entirely on each message." Before rating it, context was checked:
The finding was rated MEDIUM — an availability issue under specific conditions — rather than HIGH, which would have implied a compromise of a core security property.
// 6.3 Residual risk documentation
Post-remediation risks are listed rather than hidden:
| Risk | Mitigation | Acceptance |
|---|---|---|
| TOFU on first Service Worker visit | First visit must be over a trusted channel (Tor/loopback) | Accepted: inherent to the web model |
| Timestamps in the vault | Required for garbage collection by age | Accepted: timestamps reveal no identity |
| PQC migration pending | Shor not operational today | Accepted: active roadmap (P11) |
Documenting residuals does three things: it confirms the threat model was actually applied, it prevents a false sense of completeness, and it feeds the remediation roadmap.
7. Notes
memcpy.8. Verdict and Recommendations
// 8.1 Verdict
The cryptographic implementation is correct. The PFS (Perfect Forward Secrecy) property holds: even if the relay is compromised, messages recorded before the compromise remain encrypted, because the session tokens are wrapped in RSA-OAEP and the ephemeral ECDH secrets never cross the relay.
The "zero-trust against the relay operator" claim does not hold. The system required trust in three things the claim said it would not:
Post-remediation these are addressed, with three conditions: deployment (a) self-hosted with a benign operator is the only scenario that justifies use; (b) VPS requires additional monitoring; (c) onion adds anonymity but does not change the host's trust level. TOFU on the first visit remains; it is inherent to a web-based admin model. PQC is pending: ECDH P-256 and RSA-4096 remain vulnerable to a quantum computer.
// 8.2 Deployment recommendations
master_private.enc is encrypted at rest; its strength is the strength of the passphrase..onion identity frequently; do not run the same identity for months.// 8.3 For developers of E2EE systems
Appendix: Findings Matrix
| ID | Severity | Category | Status |
|---|---|---|---|
| H2 | HIGH | Code integrity | Remediated (P1) |
| H3 | HIGH | ECDH authentication | Remediated (P3) |
| H1 | MEDIUM | Secrets at rest | Remediated (P1/P3) |
| M1 | MEDIUM | Attestation (optional / no value) | Remediated (P9) |
| M2 | MEDIUM | Bind 0.0.0.0 vs loopback | Remediated (P2) |
| M3 | MEDIUM | Vault metadata in clear | Remediated (P5) |
| M4 | MEDIUM | Session binding | Remediated (P4) |
| M5 | MEDIUM | Vault write amplification | Remediated (P5) |
| L1 | MEDIUM | Admin route static exposure | Remediated (P1) |
| L2 | LOW | Admin-auth DoS (no cache/PoW) | Remediated (P6) |
| L3 | LOW | Cross-session file injection | Remediated (P7) |
| L4 | LOW | Unvalidated signing nonce | Remediated (P8) |
| L5 | LOW | GOLD_HASH.txt exposed | Remediated (P1) |
| L6 | LOW | Hourly window bug | Remediated (P1) |
| AD-1 | MEDIUM | Phantom client | Remediated (P4) |
| AD-3 | LOW | Silent message loss | Remediated (P10) |
| AD-4 | LOW | Re-INIT timer duplication | Remediated (P4) |
| AD-5 | MEDIUM | Session squatting | Remediated (P4) |
| C2 | LOW | File chunk no replay counter | Remediated (P8) |
| I2/I4 | INFO | Exportable ECDH / zeroization | Remediated (P8) |
| F1 | FUNC | Dead PURGE handler | Remediated (P10) |
| G3 | ROADMAP | Post-quantum migration | Planned (P11) |
Findings audited: 22 · Remediated: 21 · In roadmap: 1
Verification Summary
| Vector | Before | After |
|---|---|---|
| Admin code swap (H2) | No integrity, circular GOLD_HASH | SRI + CSP + SW pin + /admin/ + OOB hashes |
| ECDH MITM (H3) | Key unsigned, silent | RSA-PSS signature verified client-side, fail-closed |
| Session hijack (M4) | Any sessionId accepted | ECDH fingerprint bound, second key rejected |
| Vault metadata (M3) | user/filename/fileSize in clear | Ciphertext + random id only |
| Vault DoS (M5) | Full rewrite per message | Coalesced write-behind (1/s) |
| Admin route (L1) | Public static path | Token-only route |
Based on a live audit performed in a controlled lab environment. All findings remediated and verified. OMEGA is the case study; the methodology applies to any cryptographic system.
OMEGA Protocol — Technical Specification
GitHub RepositoryOMEGA is an ephemeral end-to-end encrypted communication relay that operates over Tor Hidden Services. All cryptographic operations execute in the browser through the WebCrypto API; the server acts as a blind relay that forwards fixed-size binary frames without access to message material, keys, or plaintext. This document specifies the architecture, wire protocol, cryptographic construction, and operational parameters of the reference implementation.
1. Scope and Status
This specification describes the OMEGA reference implementation. It defines normative behavior for interoperability and informative behavior for operational security. The document is versioned v1.1 and reflects the audited, remediated codebase.
| Aspect | Value |
|---|---|
| Status | Reference implementation, audited (21 findings, 20 remediated) |
| License | GPL v3.0 |
| Repository | github.com/Noir0x63/OMEGA |
| Key words | MUST, MUST NOT, SHOULD, MAY per RFC 2119 |
2. System Architecture
OMEGA consists of three logical parties connected by a single transport channel:
The relay's identity is volatile: a fresh .onion address is generated on every boot and previous key material is destroyed. The relay binds to 127.0.0.1:3000 by default; Tor publishes the hidden service.
3. Identity and Key Management
// 3.1 Master identity
A one-time keygen step generates an RSA-4096 master key pair:
| Artifact | Content | Distribution |
|---|---|---|
| master_public.pem | RSA-4096 public key (SPKI) | Injected into the client build |
| master_private.enc | RSA-4096 private key (PKCS8), AES-256-GCM encrypted | Admin-only, decrypted in browser |
| server_secrets.enc | Admin HMAC secret + server nonce (JSON) | Relay at rest |
master_private.enc is protected with a user passphrase via PBKDF2 (600,000 iterations) + AES-256-GCM. The passphrase is irrecoverable: loss of the passphrase permanently destroys the identity.
// 3.2 Ephemeral session material
The client and the operator each generate an ephemeral ECDH P-256 key pair per session. The shared secret is computed locally on both ends and never transits the relay.
Property
Perfect Forward Secrecy (PFS). The ECDH shared secret is bound into the message key derivation via HKDF. A future compromise of the RSA master key does not decrypt past sessions, because the ephemeral ECDH secret is never serialized into the RSA-encrypted INIT payload.
4. Transport and Frame Format
All traffic — signals and noise — travels as fixed 4096-byte binary frames over a single WebSocket connection:
| Offset | Size | Field | Semantics |
|---|---|---|---|
| 0 | 4 | payload length | Uint32LE; 0 = pure noise frame |
| 4 | 0..4092 | payload | UTF-8 JSON message |
| 4 + len | remainder | random padding | CSPRNG fill; defeats length correlation |
A client MUST send constant-size noise frames on a random interval (1–6 s) while connected. The relay MUST drop frames whose length field is zero or greater than 4092. Every frame must be exactly 4096 bytes on the wire.
5. Wire Protocol
Messages are JSON objects with a type field. The following message types are normative:
| Type | Direction | Purpose |
|---|---|---|
| HANDSHAKE / HANDSHAKE_ACK | C→R / R→C | Session registration (32-hex sessionId) |
| ECDH_EXCHANGE | C↔A via R | Public ECDH key relay (zero-knowledge) |
| REQ_POW / POW_CHALLENGE | C→R / R→C | Adaptive proof-of-work handshake |
| REQ_CHALLENGE / AUTH_CHALLENGE | A→R / R→A | Admin RSA-PSS challenge |
| ADMIN_AUTH | A→R | Domain-separated RSA-PSS signature |
| INIT | C→R→A | Identity + RSA-OAEP-wrapped token, attestation key |
| ATTEST_CHALLENGE / ATTEST_RESPONSE | R↔C | 30s ECDSA P-256 liveness attestation |
| ASYNC_MSG / SERVER_MSG | C↔A | AES-256-GCM encrypted messages |
| FILE_META / FILE_CHUNK | A→C | Encrypted chunked file transfer |
| BROADCAST | A→C | Encrypted broadcast to all sessions |
| HISTORY / NEW_MESSAGE | R→C/A | Vault replay and delivery |
| PURGE / PURGE_EVENT | A→R / R→all | Admin-initiated vault wipe |
// 5.1 Session lifecycle
A session is identified by a 128-bit random sessionId (32 lowercase hex). The relay accepts at most 2 concurrent connections per session and expires sessions after 1 hour. A client MUST complete the ECDH exchange within 5 s of the handshake or the relay closes the connection.
CLIENT RELAY OPERATOR
| HANDSHAKE(sid) | |
|---------------->| |
| HANDSHAKE_ACK | |
|<----------------| |
| ECDH_EXCHANGE | ECDH_EXCHANGE |
| pubKey (C) |---------------->|
| | ECDH_EXCHANGE |
| |<----------------|
| ECDH_EXCHANGE | pubKey+sig (A) |
|<----------------| |
| E2EE derived locally |
| (relay never sees secret) | 6. Cryptographic Construction
| Primitive | Purpose |
|---|---|
| AES-256-GCM | Message confidentiality + integrity, unique IV per message |
| ECDH P-256 | Ephemeral key agreement (E2EE), PFS binding |
| PBKDF2 (600k, SHA-256) | Stage-1 KDF: brute-force resistance on user token / passphrase |
| HKDF-SHA256 | Stage-2 KDF: binds ephemeral ECDH secret as salt |
| RSA-4096 OAEP | Wraps INIT payload (token, session binding) |
| RSA-4096 PSS | Admin challenge-response; signs ECDH public keys (domain-separated) |
| ECDSA P-256 | Client liveness attestation every 30 s |
| SHA-256 | PoW, ECDH fingerprint, session hashing, integrity checks |
// 6.1 Message key derivation
The AES message key is derived in two stages, identical on the client worker and the operator:
// Stage 1 — PBKDF2: brute-force resistance
pbkdfBits = PBKDF2(password=token, salt=sessionId, iters=600000, sha256, 256);
// Stage 2 — HKDF: binds the ephemeral ECDH secret (PFS)
hkdfSalt = ecdhSecret || zeroes(32);
msgKey = HKDF(ikm=pbkdfBits, salt=hkdfSalt, info="omega-v1-msg-key", sha256)
-> AES-GCM 256, non-extractable A hard failure occurs if the ECDH secret is absent at worker initialization (SEC_FAULT_NO_ECDH). No message key is ever derived without the ephemeral secret.
// 6.2 Domain separation
All RSA signatures are bound to their purpose with a domain prefix, preventing cross-protocol signature reuse:
// Admin authentication (VULN-03 mitigation)
signedNonce = "OMEGA_ADMIN_AUTH:" + nonce;
// ECDH public key authentication (H3)
signedKey = "OMEGA_ECDH:" + sessionId + ":" + publicKeyHex;
// Replay to another session fails on the sessionId component. 7. Access Control and DoS Resistance
// 7.1 Admin authentication
The admin route is a rotating HMAC path derived from a daily/hourly nonce:
dayNonce = floor(now / 86400000);
hourNonce = floor(now / 3600000);
adminPath = HMAC-SHA256(secret, dayNonce + ":" + hourNonce + ":" + serverNonce);
// The previous hour's path is accepted to avoid logout at hour rollover. Authenticating as admin requires completing adaptive PoW, then signing a challenge nonce with the RSA-PSS master key. Admin assets are served only via the token route — never as static files — and are integrity-pinned with CSP, SRI, and a Service Worker pin.
// 7.2 Proof of work
PoW is adaptive to connection load. Difficulty is the number of leading zero bits of SHA-256(nonce + challenge):
| Relay load | Difficulty (bits) |
|---|---|
| ≤ 50% connections | 16 |
| 50% – 80% | 20 |
| > 80% | 24 |
PoW is required before the admin challenge, before INIT, and before client-initiated vault writes. Challenges expire after 60 s; the message rate is limited to 50 frames per 10 s per socket.
8. Vault and Persistence
The vault stores only ciphertext records with minimal metadata. Records are truncated to the most recent 5000 and purged every 24 hours, or on admin command (PURGE).
{
"id": "<16 random bytes hex>",
"type": "ASYNC_MSG | SERVER_MSG | BROADCAST",
"payload": "<base64 AES-GCM ciphertext>",
"ts": "<epoch ms>"
} Vault writes are coalesced with a 1-second write-behind to prevent disk amplification under load. On shutdown, the vault is flushed before the process exits.
9. Operational Parameters
| Parameter | Value |
|---|---|
| Frame size | 4096 bytes |
| Max connections per session | 2 |
| Max total connections | 500 |
| Session lifetime | 1 hour |
| ECDH window | 5 s after handshake |
| PoW difficulty | 16–24 bits adaptive |
| Message rate limit | 50 / 10 s per socket |
| Vault capacity | 5000 records |
| Vault purge | every 24 h + admin PURGE |
| Attestation interval | 30 s, fail-closed after 3 misses |
| File chunk size | 2048 bytes |
10. Security Properties
The "zero-trust against the relay operator" property holds only under deployment scenario (a): self-hosted on operator-controlled hardware with a benign operator. Rented VPS (b) requires additional monitoring; Tor onion (c) adds transport anonymity without changing the host trust level. Post-quantum migration (ML-KEM) is planned; ECDH P-256 and RSA-4096 remain vulnerable to a CRQC.