Skip to content

Latest commit

 

History

History
147 lines (104 loc) · 5.2 KB

File metadata and controls

147 lines (104 loc) · 5.2 KB

Encryption Flow

This document describes the encryption flow in Dialtone, what is encrypted, what is not, and why.

Goals and threat model (short version)

  • Protect message content and channel names from the server and network observers.
  • Allow multi-device access by securely sharing symmetric keys via public key encryption.
  • Accept that compromised client endpoints can read decrypted content.

Core concepts and keys

  • Device key pair (asymmetric)

    • Each device generates a long-term key pair locally.
    • Private key is stored locally in the encrypted keystore.
    • Public key is sent to the server for key sharing.
  • Channel key (symmetric)

    • One per channel.
    • Encrypts message bodies and channel metadata (like channel names).
  • Directory key (symmetric)

    • Encrypts directory/profile data (profile display names) stored server-side.
  • Key envelopes

    • A symmetric key encrypted for a specific device using public key crypto.
    • Only the target device can decrypt it with its private key.

Username vs profile display name

  • Username

    • Used for login/identity lookup.
    • Sent in plaintext during login/register and stored only as a peppered hash.
  • Profile display name

    • Optional, user-visible name stored in the directory.
    • Encrypted with the directory key.

Data flow overview

flowchart TD
  A[User writes message] --> B[Client encrypts with channel key]
  B --> C[Ciphertext sent to server]
  C --> D[Server stores and relays ciphertext]
  D --> E[Recipient client receives ciphertext]
  E --> F[Client decrypts with channel key]
  F --> G{Another message?}
  G -->|Yes| A
  G -->|No| H[Wait for next message]
Loading

Key lifecycle and sharing

sequenceDiagram
    participant DeviceA as Device A
    participant Server
    participant DeviceB as Device B

  DeviceA->>Server: Upload public key
  DeviceB->>Server: Upload public key

    Note over DeviceA: Create channel key
  DeviceA->>Server: Create channel (encrypted name)

    Note over DeviceA: Build key envelopes
  DeviceA->>Server: Upload key envelopes

  DeviceB->>Server: Request key envelope
    Server->>DeviceB: Encrypted envelope
    Note over DeviceB: Decrypt envelope (private key)
Loading

Local keystore encryption

The client stores sensitive materials (device private key, channel keys, directory key) locally. The keystore is encrypted with:

  • scrypt KDF
  • AES-256-GCM

A passphrase is required to decrypt the keystore. If the passphrase is wrong, content remains encrypted and keys cannot be used.

What is encrypted

  • Message bodies (channel key)
  • Channel names (channel key)
  • Sender display names in messages (channel key)
  • Profile display names (directory key)
  • Stored device keys and channel/directory keys in local keystore

What is not encrypted (and why)

  • User IDs, device IDs, channel IDs

    • Needed for routing, indexing, and access control.
    • Device ID is a server-generated identifier for a specific client installation/device. It is not a cryptographic key or a public key.
  • Timestamps and message metadata

    • Needed for ordering and display.
  • Public keys

    • Must be public to enable key sharing.
  • Usernames

    • Sent in plaintext during login/register so the server can authenticate.
    • Stored only as a peppered hash (no plaintext usernames in the database).
  • Network metadata

    • Standard transport metadata (IP, timing) is outside app-level encryption scope.

Message encryption flow (detail)

  1. Sender obtains channel key (local keystore or key envelope).
  2. Client encrypts message body with the channel key.
  3. Client encrypts sender display name with the channel key.
  4. Client sends ciphertext to the server.
  5. Receiver decrypts ciphertext using the same channel key.

Message storage and encryption

  • Message bodies are encrypted client-side with the channel key before upload.
  • Sender display names in messages are encrypted client-side with the channel key.
  • The server stores and returns ciphertext for message bodies and sender names.
  • Message IDs, channel IDs, sender IDs, and timestamps are stored in plaintext for routing, indexing, and ordering.

Directory/profile encryption flow (detail)

  1. Device obtains directory key (local keystore or key envelope).
  2. Client encrypts profile display name with directory key.
  3. Server stores encrypted profile data.
  4. Other devices decrypt profile fields using directory key.

Failure and recovery behavior

  • Missing channel key: client shows "" placeholders.
  • Missing or invalid envelope: client cannot decrypt until a valid envelope is shared.
  • Wrong keystore passphrase: keys are inaccessible, decryption fails.

Security boundaries

  • Protected against server-side inspection of message content and channel metadata.
  • Not protected against compromised devices or malware on the client.
  • Key sharing relies on trusted devices correctly distributing envelopes.

Summary

Dialtone uses symmetric encryption for message bodies and channel names, and public key encryption to share those symmetric keys across devices. The server never sees plaintext message content or channel names, but it can see routing metadata required for the system to function. Usernames are sent in plaintext during auth but stored only as a peppered hash.