Cloaked in Emojis: Building an E2E Encrypted & Obfuscated Telemetry System over WebSockets

Published: (February 16, 2026 at 12:07 PM EST)
4 min read
Source: Dev.to

Source: Dev.to

Introduction

Standard telemetry and analytics endpoints are often intercepted by ad‑blockers, tampered with by malicious actors, or scraped by bots. To guarantee the integrity and delivery of usage data—such as views and interactions—developers are turning to custom, secure pipelines that combine End‑to‑End Encryption (E2EE) with an obfuscation layer over WebSockets.

Why WebSockets?

  • Persistent, bidirectional channel – harder to spot than traditional HTTP analytics requests.
  • Resilient to simple deep packet inspection (DPI) – the traffic looks like any other real‑time socket communication.
  • Built‑in keep‑alive – ping heartbeats detect dead sockets.

Client‑Side Architecture (Angular)

  1. Connection management

    • A dedicated service opens a WebSocket to the analytics endpoint.
    • The connection is automatically recycled every 120 000 ms to keep the session healthy.
  2. Tracking identifier

    • If a registered user token is unavailable, a random UUID v4 is generated and stored in localStorage as a fallback tracking ID.
  3. Heartbeat

    • The server sends a ping every 30 000 ms; the client replies with a pong to keep the socket alive.

Security Handshake

StepDescription
Client initiationOpens the WebSocket and passes its public key via a base64‑encoded query parameter (?pub=…).
Server key generationGenerates an ephemeral RSA‑OAEP key pair for the session.
Session alphabet generationCreates a random 32‑byte seed and derives a unique 64‑character Base64 alphabet for the session.
Secure exchangeEncrypts the session alphabet with the client’s public key (RSA‑OAEP) and signs the encrypted payload with the server’s private key (RSA‑PSS).

Emoji‑Based Obfuscation (EmojiCodec)

The payload is transformed into a string of emojis instead of standard binary or Base64 data.

  • Alphabet – 64 distinct emojis (e.g., 🚀, 🌈, 🌋, 🎁) map one‑to‑one to Base64 indices.
  • Object shuffling – JSON keys are randomized before encoding, ensuring identical data yields different strings.
  • Dynamic padding – A timestamp and a random client ID (CID) are injected to guarantee uniqueness.
  • Caesar‑shift cipher – A random emoji is placed at the start of the string as the “key index.” Each subsequent emoji is shifted along the emoji array based on this key, providing a polymorphic Caesar cipher.

Example (pseudo‑code)

// Encode payload to emoji string
function encodeEmoji(payload: object, emojiAlphabet: string[]): string {
  const shuffled = shuffleObjectKeys(payload);
  const padded = { ...shuffled, ts: Date.now(), cid: randomCID() };
  const json = canonicalStringify(padded);
  const base64 = btoa(json);
  const emojiBase = base64ToEmoji(base64, emojiAlphabet);
  const keyIdx = randomEmoji(emojiAlphabet);
  return applyCaesarShift(emojiBase, keyIdx, emojiAlphabet);
}

Canonical JSON Stringification

Because JavaScript engines may order object keys differently, digital signatures on raw JSON strings can fail. The system uses a strict canonicalStringify function:

  • Recursively sorts all object keys alphabetically.
  • Converts the sorted object to a string before signing.

Example (pseudo‑code)

function canonicalStringify(obj: any): string {
  if (Array.isArray(obj)) {
    return '[' + obj.map(canonicalStringify).join(',') + ']';
  }
  if (obj && typeof obj === 'object') {
    const keys = Object.keys(obj).sort();
    return '{' + keys.map(k => `"${k}":${canonicalStringify(obj[k])}`).join(',') + '}';
  }
  return JSON.stringify(obj);
}

Server‑Side Processing

  1. Decoding – The server receives the emoji string, reverses the Caesar shift, maps emojis back to Base64, and decrypts the session alphabet.
  2. Canonicalization – The resulting JSON is canonicalized using the same canonicalStringify routine.
  3. Signature verification – The server verifies the payload signature with the client’s public key (supports ECDSA or RSA‑PSS).
  4. Schema validation – Events must be one of VIEW, LIKE, or ADMIRE. Valid events are forwarded to a StatManager.

Idempotency & Duplicate Prevention

  • When a VIEW event occurs, an idempotency key is generated from the event’s entity ID and the user’s session token.
  • The key is stored in a cache with a 1‑hour expiration (60 × 60 seconds).
  • Duplicate requests within this window are ignored, preventing metric inflation from retries or malicious users.

Conclusion

By layering robust WebCrypto algorithms beneath a mutating, emoji‑based obfuscation codec, this architecture ensures telemetry data remains:

  • Confidential – encrypted end‑to‑end.
  • Untampered – signatures verified against a canonical representation.
  • Resilient – difficult for ad‑blockers, DPI, or bots to detect or manipulate.

The result is a secure, low‑profile telemetry pipeline that can operate reliably even in hostile network environments.

0 views
Back to Blog

Related posts

Read more »

A DuckDB-based metabase alternative

Shaper Open Source, SQL-driven Data Dashboards powered by DuckDB. Learn more: !Screenshothttps://camo.githubusercontent.com/c19dae1a90aedb46f87d57b780d32dabe1e...