Messaging Mechanics

Group Shared Pad Architecture

Arithmetic lanes, slot assignment, full-mesh delivery, and background resync sweeps.

Overview

Wiltkey groups do not use key distribution centers. Instead, every member shares one group seed and derives a common group keystream from it, using the same SHA-256 counter-mode stream cipher described in Encryption & OTP. Unlike a 1-on-1 chat (which stores a consumed pad on disk), the group keystream is computed on demand from the seed — there is no stored pad file. That keystream is arithmetically partitioned into dedicated member lanes; because the lane geometry is fixed and any member can recompute any lane from the shared seed, clients decrypt incoming group messages directly, without routing through a central server or relying on a single group owner to relay them. (“Shared Pad” below is a nickname for this shared, seed-derived keystream — not a one-time pad in the information-theoretic sense.)

Wiltkey supports two group chat operational models sharing this identical underlying stream cipher:

  • Byte-budget groups: Unlimited time duration with a fixed data budget (keystream lane size), designed for long-term, high-security communications.
  • Time Wilt groups: Limited time duration with an unlimited budget (a large keystream allotment with no storage limit to worry about for the life of the chat), designed for temporary, get-to-know-people situations like events, meetups, and short-lived teams. Created from the Connect tab → “Time Wilt group.”

Shared Pad Geometry

Info Lane (1MB) Slot 1: Member 1 Lane Slot 2: Member 2 Lane Slot 3: Member 3 Lane Offset 0 1MB 1MB + laneSize 1MB + 2*laneSize Lane Start Offset = 1MB + (slotIndex - 1) * laneSize

How it Works

  1. Fixed Partitioning: The group pad begins with a 1MB Info Lane (offset 0 to 1,048,576 bytes). This lane is reserved for metadata updates (profiles, membership, custom emojis). Offsets above 1MB are divided into member lanes of size laneSize. A member assigned to slotIndex writes exclusively to their lane starting at:
    laneStart = AppState.infoLaneSize + (slotIndex - 1) * laneSize
  2. BLE Slot Provisioning: The group owner registers new members in person over BLE. The owner fetches empty lanes from the group database, assigns the member the next available slotIndex, encrypts the group seed, and transmits it. The owner then broadcasts a group_info_update metadata frame over the WebSocket.
  3. Time Wilt Lifetime & Renewal Mechanics: Time Wilt groups reuse the same lane encryption mechanism as byte-budget groups, but substitute data budget limits for time limits:
    • Per-Member Countdown: Each member's countdown begins when they meet the host in person over BLE. When a member's timer expires, the group becomes read-only for that member until they meet the host again in person to renew their time.
    • Host & Revival Rules: The host has no countdown. The group only goes quiet once every member has wilted, and meeting any active member or host revives it.
    • Duration & Member Tier Caps: Lifetimes range from 1 hour to 30 days for free accounts, and up to 6 months with WiltKey Plus. Time Wilt groups support up to 20 members for free, and up to 100 members for WiltKey Plus subscribers.
  4. Optimized Single-Upload Relay Delivery: Starting in v1.1.0, group messages (especially images) send once from the client and are delivered to every member by the relay, instead of the sender uploading a separate copy for each member. This delivers much faster sending speeds and drastic savings on mobile data for the sender, while maintaining complete zero-knowledge relay blindness (the relay routes opaque ciphertexts by recipient without being able to read payload contents).
  5. Democratic Vote-to-Nuke: Destroying a group “for everyone” is a group vote. Any member can propose a group destruction vote, and a majority of the other members must agree before the group_nuke signal is executed and the chat is wiped for all participants.
  6. Gap Resync Sweeps: If a client goes offline, the server queue may drop messages from new members. To heal, on opening the chat or reconnecting, the client triggers `autoSyncGroup`. It requests a full resync range sweep (offset 0 to totalGroupSize) from all members via `chat_resync_request`. Peers query their local databases and send back a `chat_resync_response` containing the missing envelopes.

Smart Lane Gap Audit & Priority Resync

Rather than blindly broadcasting resync requests across every slot, Wiltkey runs an automated in-database byte-offset gap audit (auditAndSyncGroupLanes) when a group chat is opened or when reconnecting to the relay:

  • Slot Header Audit: Confirms the first 128 bytes (AppState.laneHeaderSize) for every active member slot are present.
  • Internal Hole Detection: Sorts stored messages by keystream offset and discovers gaps [M_i.offset + M_i.length, M_{i+1}.offset).
  • Tail Write Verification: Scans if the SQLite lane tracking pointer exceeds the latest locally saved message offset.

When gaps are detected, sync requests are dispatched to members using prioritized candidate ranking with automatic 5-second fallbacks:

CANDIDATE PRIORITY HIERARCHY
1. Most Recent Active Chatter (excluding self — queried via WiltkeyDatabase.getMostRecentSender)
2. Group Host (contact.hostKeyHash)
3. Slot Owner (member_key_hash for that specific lane)
4. Remaining Active Group Members
⚡ CLEAN RANGE AUDIT CACHING
When a peer returns a chat_resync_response (even if containing an empty confirmation messages: []), that byte range is marked clean in cleanGapAuditCache for 15 minutes, preventing network spam while ensuring instantaneous message healing.

Member Mentions & Shortcode Routing

Because member names can change, collide, or contain arbitrary characters, Wiltkey enforces cryptographic identity for mentions rather than fragile plaintext name matching.

  • Autocomplete Bar (MentionAutocompleteBar): Typing @ in the composer scans active group members, matching against display names while inserting their permanent 8-character hex shortcode (e.g., @A1B2C3D4).
  • Zero Keystream Leakage: Mention tokens are rendered inline within the encrypted message body on the stream cipher channel. No unencrypted metadata indicates who is mentioned.
  • Recipient Highlighting & Alert Routing: On message reception, _handleGroupPayload scans for @SHORTCODE tokens matching the local user's own shortcode or direct quote-replies to their message IDs. If found, the message bypasses general chat muting filters (when set to Mentions & replies only) and logs an entry to the Dashboard Events feed.

Key Files & Symbols

File Path Symbol Name Description
lib/core/state_groups.dart laneStartFor() Calculates the absolute keystream start offset for a slot index: 1MB + (slot - 1) * laneSize.
lib/features/chat/…/mention_autocomplete_bar.dart MentionAutocompleteBar Floating member search & shortcode insertion widget above the group composer.
lib/core/state_groups.dart auditAndSyncGroupLanes() Scans SQLite for missing headers, message holes, and tail gaps across all member slots.
lib/core/state_inbound.dart _getSyncCandidates() Ranks sync targets (most recent chatter → host → slot owner → other members).
lib/core/state_groups.dart sendGroupMessage() Writes payload to active lane, increments pointer, and sends to all member hashes over WebSockets.
lib/core/state_groups.dart autoSyncGroup() Announces profile, pulls metadata, and executes auditAndSyncGroupLanes().
lib/core/state_inbound.dart _handleGroupPayload() Decodes incoming group frames, performs gap checks, mention routing, and updates lane write offsets.

Gotchas & Edge Cases

⚠️ MEMBER-TO-MEMBER METADATA DISCOVERY
Because members discover each other's profiles from lane headers or owner broadcasts, a member might receive a message from a peer before processing their profile. The client automatically constructs a placeholder profile "Member " and triggers a background metadata request to keep the UI from stalling.