Keys & Encryption Model

Everything inside Nyxen is built around one uncompromising design: keys never leave the user’s device. This page explains how Nyxen handles encryption, key derivation, and relay logic—without requiring you to be a cryptographer to understand it.
Core Principles
Client-side encryption
All encryption and decryption happens locally in the browser or client app.
No plaintext transmission
Nyxen’s servers see only ciphertext, metadata for routing, and TTLs.
Key derivation, not sharing
Each primitive (Dead Drop, Board, Capsule, etc.) derives unique subkeys from a root key using HKDF.
Zero knowledge
Nyxen cannot decrypt, inspect, or index your data.
Ephemeral keys
Keys are short-lived and discarded on expiry or burn.
[!NOTE] This model protects against data compromise at rest on Nyxen’s infrastructure. It does not protect against endpoint compromise—users must keep their devices secure.
The Encryption Stack
Algorithms
Symmetric encryption
AES-GCM-256
Encrypts message, file, or content block. Provides confidentiality + integrity.
Key derivation
HKDF (SHA-256)
Derives unique subkeys for different components.
Key generation
Crypto.getRandomValues()
Produces random 256-bit keys in-browser.
Transport security
TLS 1.3 / DTLS-SRTP
Protects transport between client and Nyxen relays.
All cryptographic operations use Web Crypto API in the web client or libsodium equivalents in native builds.
Key Hierarchy
Nyxen uses a tree-like key structure.
Capsule Key (root)
├── Dead Drop Key
├── Board Key
├── File Drop Key
├── Signals Key
├── Ghost Code Key
└── Spectre Voice KeyEach derived key is unique to its purpose.
Example (pseudo-code)
const capsuleKey = generateKey(256);
function deriveKey(rootKey, label) {
return hkdf(rootKey, "nyxen-derivation", label);
}
// For each primitive:
const deadDropKey = deriveKey(capsuleKey, "dead-drop");
const boardKey = deriveKey(capsuleKey, "ephemeral-board");
const fileKey = deriveKey(capsuleKey, "file-drop");[!TIP] Each component key is independent. Compromise of one does not reveal others.
Encryption Flow (Simplified)
1. Generate Key
Client generates a new AES-GCM key using browser cryptography.
const key = crypto.getRandomValues(new Uint8Array(32));2. Encrypt Payload
Data is encrypted before leaving the client.
const { ciphertext, nonce, authTag } = encryptAESGCM(key, JSON.stringify(message));3. Transmit Ciphertext
Relay receives only encrypted data + TTL.
{
"capsule_id": "C-IR492",
"ciphertext": "base64...",
"nonce": "base64...",
"ttl_seconds": 1800
}4. Expire / Burn
On TTL or burn event:
relay deletes ciphertext;
clients wipe their keys and caches.
onExpire() {
delete(ciphertext);
clearKey();
}5. Decrypt (Client-side)
Only peers with the same key can decrypt.
const message = decryptAESGCM(key, ciphertext, nonce);Key Handling Rules
Keys are generated per context
No global “account key.” Every Dead Drop, Capsule, etc. has its own.
Keys are never stored server-side
Relays only store encrypted payloads.
Keys can be shared manually
Users exchange keys out-of-band (e.g., another Nyxen channel, QR, etc.).
Keys are cleared on expiry
Client deletes keys when TTL ends or user burns manually.
No password recovery
Lose your key, lose access — by design.
[!WARNING] There is no “forgot my password” function in Nyxen. Losing the key means permanent data loss.
Relay Interaction
Nyxen relays are dumb couriers:
They route encrypted data between peers.
They enforce TTLs and purge expired content.
They never decrypt, inspect, or store long-term logs.
Relay Log Example (minimal):
{
"capsule_id": "C-IR492",
"message_id": "m13",
"ttl_seconds": 600,
"expiry": "2025-11-11T22:15:00Z"
}After expiry, this record is deleted automatically.
Encryption and TTL Binding
Every encrypted payload carries TTL metadata:
ttl_seconds
How long ciphertext may exist
expires_at
Exact UTC expiration timestamp
burn
Boolean flag for manual destruction
context_id
Capsule or object linkage
When TTL or burn triggers:
The relay deletes the ciphertext.
Clients purge associated keys.
UI displays “burn notice.”
if (now >= expires_at || burn) {
clearLocalStorage();
showNotice("This object has been destroyed.");
}Example: Encrypted Message Structure
{
"version": "1.0",
"context": "dead-drop",
"nonce": "A1B2C3...",
"ciphertext": "V0dBQm9keS9lbnRyeQ==",
"ttl_seconds": 1800,
"created_at": "2025-11-11T21:45:00Z"
}Architectural Diagram
[ User A ] --encrypt--> [ Relay (ciphertext only) ] --decrypt--> [ User B ]
| |
TTL ends → client burn + relay purge → total deletionSecurity Posture
Server compromise
No plaintext on server
Relay metadata leak
Minimal routing data, no content
Key reuse
Per-context key derivation
Endpoint theft
Out of scope (user responsibility)
Data retention
TTL enforced + burn capability
Replay
Nonce + authTag validation per message
[!NOTE] Nyxen is resilient to data compromise on its infrastructure. It is not resistant to an infected client or user voluntarily leaking keys.
Future Considerations
Planned research and upgrades:
Post-quantum key exchange support (X25519 → Kyber hybrid)
Multi-device sync with client-side key escrow (optional, local-only)
Visual key-pair indicators for context awareness
Hardware-backed storage (WebAuthn integration)
Nyxen’s encryption model is not built for marketing language; it’s built for certainty. If you hold the key, you can read the data. If you don’t, you can’t. Even Nyxen can’t.
Last updated

