OMEGA Protocol: Auditing and Hardening

Author
Eduardo Camarillo [Noir0x63]
Date
Version
v1.1

Quick Answer

Complete audit cycle of Protocol OMEGA, from adversary definition to post-remediation verification. 21 findings (2 HIGH, 7 MEDIUM), 20 remediated and verified. Four findings directly contradicted the zero-trust relay claim.

Key Takeaways

  • Category: Protocolo OMEGA
  • Version: v1.1
  • Published: 2026-08-12
  • Keywords: security audit methodology, threat modeling, E2EE audit, whitebox static analysis, blackbox verification

OMEGA Protocol: Auditing and Hardening

GitHub Repository
Date: Fecha: August 12, 2026
Auditor: Auditor: Eduardo Camarillo [Noir0x63]
Version: Versión: v1.1
21 findings · 20 remediated

Complete 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 controlActive control of up to 30% of overlay nodes (Tor)Can observe circuits, replay frames, and correlate traffic across the network
Traffic analysisIAT (Inter-Arrival Time) classifiers based on Transformer architectureCan distinguish real sessions from noise padding by timing patterns
Indefinite captureMass storage under Harvest-Now-Decrypt-LaterRecords ciphertext today on the assumption it can be decrypted later
Quantum capabilityPolynomial-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:

(a)Self-hosted on operator-owned hardware. The operator controls the OS, the filesystem, and the network path.
(b)Rented VPS. A third party has administrative access to the host and the ability to read the filesystem.
(c)Tor onion. The .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 endpointsStandard assumption in protocol analysis. Without it, every system is trivially broken by keylogging or memory scraping
Host compromise before the operator's first sessionInherent to self-hosting. The defense is a strong passphrase plus encrypted key material at rest
Quantum computers in production todayNot 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:

01.Data flow — trace each input to its crypto sink. Is it validated on the way? Are intermediate copies of secrets ever left in memory?
02.Spec vs. code — does the implementation actually deliver the property the README claims?
03.Threat-specific — for each risk in the model (MITM, replay, metadata leakage, supply chain), is the defensive code present? Absence is itself a finding.

// 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:

L1 already exposed the admin route as a static file, so the secret does not buy an attacker a new capability — the panel is already reachable.
Under (a) self-hosted, filesystem read access implies the host is already compromised; a plaintext secret on disk adds nothing.
Under (b) VPS, the provider can read the filesystem by definition; that is the accepted trade-off of renting a server.

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

Host: OMEGA relay + Tor, with the hidden service published.
Auditor: separate Kali VM connecting through Tor.

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:

Key substitution breaks the signature; the client fails closed before any shared secret is derived.
Replay to another session breaks on the 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.

// Atomicity. The check-and-set runs on the Node.js event loop, which is single-threaded. Two frames arriving at the same millisecond are processed sequentially: the first sets the fingerprint, the second observes it already exists and is rejected. There is no read-then-write interleaving, so there is no race condition to exploit.

6. Report Structure

// 6.1 Sections

The final report followed six sections so each finding is auditable end to end:

1.Threat model — adversary, capabilities, exclusions. Prevents scope disputes.
2.Findings matrix — ID, severity, evidence, remediation. A single place to see everything.
3.Root cause — which design decision produced each finding, rather than just the symptom.
4.Remediation plan — every finding mapped to a remediation package (P1–P11).
5.Verification — static analysis, dynamic observation, or both, for each finding.
6.Residual risks — what remains after remediation, with acceptance rationale.

// 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 vault is in-memory until a flush; the bottleneck is disk I/O, not CPU.
The vault stores ciphertext only; no plaintext is exposed.
Reaching 500+ messages per second requires bypassing the Proof-of-Work gate.
In the self-hosted single-operator scenario, the DoS would be directed at the operator's own relay.

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 visitFirst visit must be over a trusted channel (Tor/loopback)Accepted: inherent to the web model
Timestamps in the vaultRequired for garbage collection by ageAccepted: timestamps reveal no identity
PQC migration pendingShor not operational todayAccepted: 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

1.The threat model is committed to writing first. Disagreements over a finding are, more often than not, disagreements over the threat model rather than the code.
2.Static analysis surfaces implementation bugs. Architectural defects — "the code implements RSA-PSS correctly, but is RSA-PSS the right primitive here?" — require reading the design intent, not grepping for memcpy.
3.Blackbox observation is mandatory. Static analysis and implementation can both be wrong; only capture confirms behavior, and it exposes environment-specific behavior and out-of-code mitigations.
4.Remediation is layered, not single-mechanism. H2 uses five redundant controls; the residual risk is the joint probability of all five failing, not any one.

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:

Integrity of code served by the relay (H2)
Authenticity of ECDH keys (H3)
Isolation of sessions (M4)

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

1.Deploy on operator-controlled infrastructure (scenario a).
2.Verify build outputs offline — capture hashes at build time, store them out-of-band, and verify before using the admin panel.
3.Use a strong passphrase. master_private.enc is encrypted at rest; its strength is the strength of the passphrase.
4.Set a post-quantum migration deadline (suggested 2030) and track it.
5.Rotate the .onion identity frequently; do not run the same identity for months.

// 8.3 For developers of E2EE systems

1.Formalize the threat model before writing "trustless" into the README.
2.Confidentiality and authenticity are separate properties. Encryption stops eavesdropping; it does not stop tampering.
3.Sign ephemeral ECDH keys, and bind the signature to each party's identity and to the session.
4.Do not serve the client's verification code from the same relay the code verifies.
5.Document deployment assumptions explicitly; if the system only works under one deployment, say so.

Appendix: Findings Matrix

ID Severity Category Status
H2HIGHCode integrityRemediated (P1)
H3HIGHECDH authenticationRemediated (P3)
H1MEDIUMSecrets at restRemediated (P1/P3)
M1MEDIUMAttestation (optional / no value)Remediated (P9)
M2MEDIUMBind 0.0.0.0 vs loopbackRemediated (P2)
M3MEDIUMVault metadata in clearRemediated (P5)
M4MEDIUMSession bindingRemediated (P4)
M5MEDIUMVault write amplificationRemediated (P5)
L1MEDIUMAdmin route static exposureRemediated (P1)
L2LOWAdmin-auth DoS (no cache/PoW)Remediated (P6)
L3LOWCross-session file injectionRemediated (P7)
L4LOWUnvalidated signing nonceRemediated (P8)
L5LOWGOLD_HASH.txt exposedRemediated (P1)
L6LOWHourly window bugRemediated (P1)
AD-1MEDIUMPhantom clientRemediated (P4)
AD-3LOWSilent message lossRemediated (P10)
AD-4LOWRe-INIT timer duplicationRemediated (P4)
AD-5MEDIUMSession squattingRemediated (P4)
C2LOWFile chunk no replay counterRemediated (P8)
I2/I4INFOExportable ECDH / zeroizationRemediated (P8)
F1FUNCDead PURGE handlerRemediated (P10)
G3ROADMAPPost-quantum migrationPlanned (P11)

Findings audited: 22 · Remediated: 21 · In roadmap: 1

Verification Summary

Vector Before After
Admin code swap (H2)No integrity, circular GOLD_HASHSRI + CSP + SW pin + /admin/ + OOB hashes
ECDH MITM (H3)Key unsigned, silentRSA-PSS signature verified client-side, fail-closed
Session hijack (M4)Any sessionId acceptedECDH fingerprint bound, second key rejected
Vault metadata (M3)user/filename/fileSize in clearCiphertext + random id only
Vault DoS (M5)Full rewrite per messageCoalesced write-behind (1/s)
Admin route (L1)Public static pathToken-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.

` }; window.ARTICLES_CONTENT['omega-spec'] = { title: "OMEGA Protocol — Technical Specification", date: "2026-08-12", author: "Eduardo Camarillo [Noir0x63]", version: "v1.1", content: `

OMEGA Protocol — Technical Specification

GitHub Repository
Date: Fecha: August 12, 2026
Author: Autor: Eduardo Camarillo [Noir0x63]
Version: Versión: v1.1
Informative — Protocol Reference

OMEGA 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
StatusReference implementation, audited (21 findings, 20 remediated)
LicenseGPL v3.0
Repositorygithub.com/Noir0x63/OMEGA
Key wordsMUST, MUST NOT, SHOULD, MAY per RFC 2119

2. System Architecture

OMEGA consists of three logical parties connected by a single transport channel:

01.Client — a browser page. Generates ephemeral ECDH keys, derives AES session keys, encrypts/decrypts messages in a Web Worker.
02.Operator (Admin) — a browser panel. Authenticates with RSA-PSS, terminates E2EE, stores no plaintext outside RAM.
03.Relay — a Node.js/Express + WebSocket server. Forwards fixed-size frames; never holds keys or plaintext.

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.pemRSA-4096 public key (SPKI)Injected into the client build
master_private.encRSA-4096 private key (PKCS8), AES-256-GCM encryptedAdmin-only, decrypted in browser
server_secrets.encAdmin 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
04payload lengthUint32LE; 0 = pure noise frame
40..4092payloadUTF-8 JSON message
4 + lenremainderrandom paddingCSPRNG 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_ACKC→R / R→CSession registration (32-hex sessionId)
ECDH_EXCHANGEC↔A via RPublic ECDH key relay (zero-knowledge)
REQ_POW / POW_CHALLENGEC→R / R→CAdaptive proof-of-work handshake
REQ_CHALLENGE / AUTH_CHALLENGEA→R / R→AAdmin RSA-PSS challenge
ADMIN_AUTHA→RDomain-separated RSA-PSS signature
INITC→R→AIdentity + RSA-OAEP-wrapped token, attestation key
ATTEST_CHALLENGE / ATTEST_RESPONSER↔C30s ECDSA P-256 liveness attestation
ASYNC_MSG / SERVER_MSGC↔AAES-256-GCM encrypted messages
FILE_META / FILE_CHUNKA→CEncrypted chunked file transfer
BROADCASTA→CEncrypted broadcast to all sessions
HISTORY / NEW_MESSAGER→C/AVault replay and delivery
PURGE / PURGE_EVENTA→R / R→allAdmin-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-GCMMessage confidentiality + integrity, unique IV per message
ECDH P-256Ephemeral key agreement (E2EE), PFS binding
PBKDF2 (600k, SHA-256)Stage-1 KDF: brute-force resistance on user token / passphrase
HKDF-SHA256Stage-2 KDF: binds ephemeral ECDH secret as salt
RSA-4096 OAEPWraps INIT payload (token, session binding)
RSA-4096 PSSAdmin challenge-response; signs ECDH public keys (domain-separated)
ECDSA P-256Client liveness attestation every 30 s
SHA-256PoW, 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% connections16
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 size4096 bytes
Max connections per session2
Max total connections500
Session lifetime1 hour
ECDH window5 s after handshake
PoW difficulty16–24 bits adaptive
Message rate limit50 / 10 s per socket
Vault capacity5000 records
Vault purgeevery 24 h + admin PURGE
Attestation interval30 s, fail-closed after 3 misses
File chunk size2048 bytes

10. Security Properties

E2EE confidentiality — AES-256-GCM keys derived only from material that never transits the relay.
Perfect Forward Secrecy — ephemeral ECDH bound into KDF; RSA compromise cannot decrypt history.
Authenticated ECDH — operator signs its ephemeral key with RSA-PSS, bound to sessionId.
Session binding — sessionId pinned to the first ECDH fingerprint; substitution rejected.
Code integrity — client worker SHA-512 pinned; admin assets CSP + SRI + Service Worker pin.
Replay resistance — message and file-chunk monotonic counters.
Traffic analysis resistance — fixed frames, random padding, stochastic noise, no IP rate limiting.
Memory hygiene — plaintext buffers zeroized after use; private keys non-extractable.

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.

Related Articles