Connection lost
Attempting to reconnect
Something went wrong
Attempting to reconnect
sTELgano-std-1
Open Protocol · Version 1.0 · April 2026
Overview
sTELgano-std-1 is an open protocol for contact-layer steganographic messaging. It defines how two parties establish and use an encrypted communication channel hidden inside a phone contact. The protocol covers identifier derivation, key generation, message encryption, transport, access control, and data lifecycle -- designed for independent implementation and self-hosting.
Core Invariants
N=1
At most one message exists per room at any time. Replies atomically delete the previous message in a single database transaction. No history exists anywhere.
Server Blindness
No server-side function accepts plaintext phone numbers or PINs. The server only processes opaque SHA-256 hashes and AES-256-GCM ciphertext.
Client-Side Crypto
All key derivation and encryption/decryption happens in the browser via the Web Crypto API. The server never touches plaintext or key material.
Identifiers
All identifiers are derived client-side using SHA-256. Each serves a distinct purpose in the protocol. The salts are public constants, optionally overridable for self-hosted instances.
Uniquely identifies the room. Derived solely from the phone number. Both parties compute the same hash from the shared steg number.
Proves the caller knows the correct PIN. Each party has a different access_hash because they each choose a different PIN.
Identifies the sender within a room. Because access_hash is an input, two users with the same phone but different PINs produce different sender identities.
The symmetric encryption key. PIN is NOT part of the derivation because both users need the same key but have different PINs.
Key Design Decisions
-
PIN is NOT part of enc_key
Both users need the same encryption key to read each other's messages, but they each choose a different PIN. If PIN were part of the key, messages would be unreadable by the other party.
-
access_hash IS part of sender_hash
This ensures that two users with the same phone number but different PINs produce different sender identities. Without this, a single user could impersonate both sides of a conversation.
-
600,000 PBKDF2 iterations
Follows the OWASP 2023 recommendation for password-based key derivation. At ~2 seconds per derivation, brute-force attacks on the encryption key become computationally infeasible.
-
Salts are public constants
The salts are embedded in the client-side JavaScript. They can be overridden by self-hosters, but rotating salts is a breaking change -- all existing rooms become permanently inaccessible.
Message Encryption
AES-256-GCM
Transport
Phoenix Channels
Real-time communication over WebSocket using Phoenix Channels. The socket is fully anonymous -- no session cookie, no authentication token, no user identity. Connection state is entirely ephemeral.
Channel Events
Join requires three 64-character hex strings: room_hash, access_hash, and sender_hash.
Access Control
| Mechanism | Behavior |
|---|---|
| Room Creation | First join with a valid room_hash creates the room automatically |
| RoomAccess | Server stores (room_hash, access_hash) pairs to validate PIN correctness |
| Lockout | 10 failed access attempts trigger a 30-minute lock on that access_hash |
| Room Expiry | Optional TTL per room, enforced by an hourly background worker that also hard-deletes the room's messages and access records |
| Max Occupancy | Two access_hash entries per room (the two conversation parties) |
Data Lifecycle
Messages
Hard-deleted immediately on reply (N=1 invariant). The previous message row is permanently removed from the database in the same transaction that inserts the new message. No deferred purge, no soft-delete window.
Rooms
Expire at their configured TTL. An hourly background worker deactivates expired rooms and, in a single atomic transaction, hard-deletes every message and every (room_hash, access_hash) record so no long-term linkability of past attempts survives.
Sessions
Stored in browser sessionStorage only (up to 6 keys, including an optional extension secret when paid tiers are enabled). Cleared automatically on logout, panic route (/x), or room expiry. Never sent to the server. Never persisted to disk.
Self-Hosting
Run Your Own Instance
sTELgano-std-1 is designed for self-hosting. The four cryptographic salts (ROOM_SALT, ACCESS_SALT, SENDER_SALT, ENC_SALT) can be customized via environment variables, creating a completely independent namespace. Rooms on one instance cannot interact with rooms on another.
Rotating salts after deployment is a breaking change. All existing rooms will become permanently inaccessible.
Version History
| Version | Date | Notes |
|---|---|---|
| std-1 | April 2026 | Initial release. Defines contact-layer steganographic messaging with SHA-256 identifiers, AES-256-GCM encryption, PBKDF2 key derivation, Phoenix Channel transport, and N=1 message invariant. |