Skip to Content
Multi-Device Support

Multi-Device Support

Technical specification for identity management across multiple devices.

Overview

Zentalk supports using a single identity across multiple devices while maintaining E2EE security. Each device has its own cryptographic keys, but shares the Identity Key.

Key Hierarchy

Key TypeScopePurpose
Identity Key (IK)AccountUser identification, shared across devices
Device Key (DK)Per-deviceUnique to each device, signs messages
Pre-KeysPer-deviceEach device publishes own prekeys
Session KeysPer-deviceSeparate sessions per device

Key Relationship

Identity Key (IK) ├── Device Key 1 (Phone) │ ├── Signed Pre-Key 1 │ └── One-Time Pre-Keys [100] ├── Device Key 2 (Desktop) │ ├── Signed Pre-Key 2 │ └── One-Time Pre-Keys [100] └── Device Key 3 (Tablet) ├── Signed Pre-Key 3 └── One-Time Pre-Keys [100]

Device Linking

Methods

MethodSecurityConvenience
QR Code scanHighMedium
Numeric codeHighMedium
Cloud backupMediumHigh

QR Code Linking Protocol

1. Primary device generates linking request: - Ephemeral X25519 keypair (EK_P) - Random session ID - Timestamp 2. QR code contains: QR = Base64(EK_P_pub || session_id || timestamp || signature) 3. New device scans QR: - Generates own ephemeral key (EK_N) - Computes shared secret: SS = X25519(EK_N, EK_P_pub) 4. New device sends to primary: - EK_N_pub - Device public keys (encrypted with SS) 5. Primary verifies and responds: - Identity Key (encrypted with SS) - Existing session states (encrypted) - Contact list (encrypted) 6. Both devices verify via numeric code: - code = HKDF(SS, "verify")[0:6] - User confirms codes match

Security Properties

PropertyMechanism
MITM preventionOut-of-band verification (QR/code)
Replay preventionTimestamp + session ID
Forward secrecyEphemeral keys deleted after linking

Device Registration

Each device registers with the server independently:

DataStorage
Device IDServer (pseudonymous)
Device public keysServer (for message routing)
Pre-key bundleServer (per-device)
Device nameEncrypted, client-only

Key Bundle per Device

Device Key Bundle: ┌─────────────────────────────────────────┐ │ Identity Key (shared) │ ├─────────────────────────────────────────┤ │ Device Key (unique) │ ├─────────────────────────────────────────┤ │ Signed Pre-Key (unique) │ ├─────────────────────────────────────────┤ │ One-Time Pre-Keys [100] (unique) │ └─────────────────────────────────────────┘

Message Delivery

Multi-Device Encryption

When Alice sends to Bob (who has 3 devices):

1. Alice fetches Bob's device list (3 devices) 2. For each device, Alice: - Performs X3DH with device's key bundle - Creates/updates session for that device - Encrypts message with device-specific key 3. Server stores 3 encrypted copies - One for each of Bob's devices - Each decryptable only by target device 4. Each device receives and decrypts independently

Fanout Table

Sender DevicesRecipient DevicesEncrypted Copies
111
133
236
nmn × m

Own-Device Sync

Messages sent from one device sync to others:

1. Alice sends message from Phone 2. Phone encrypts for: - Bob's devices (recipients) - Alice's Desktop (self-sync) - Alice's Tablet (self-sync) 3. All Alice's devices receive copy

Session Management

Per-Device Sessions

PeerSessions
Bob (3 devices)3 separate Double Ratchet sessions
Carol (1 device)1 session
Group (10 members × 2 devices avg)20 Sender Key distributions

Session Storage

DataStorageEncryption
Ratchet statePer-device IndexedDBAES-256-GCM
Message historySynced across devicesE2EE
Contact listSynced across devicesE2EE

Conflict Resolution

When multiple devices operate on shared state, conflicts can arise. This section describes how Zentalk detects and resolves conflicts while maintaining cryptographic consistency.

Why Conflicts Happen

Conflicts occur in distributed systems when multiple devices modify shared state without coordination:

CauseDescription
Simultaneous editingTwo devices modify contact list at the same time
Network partitionsDevices operate offline, creating divergent histories
Race conditionsMessages arrive in different orders on different devices
Clock driftDevice timestamps disagree on event ordering

Conflict Types

Conflict TypeExampleResolution
Contact list editsDevice A blocks user, Device B adds same userLast-Write-Wins with vector clock
Message history syncDifferent message order on Phone vs DesktopCausal ordering via Double Ratchet counters
Read status conflictsMessage marked read on one device, unread on anotherUnion merge (read wins)
Profile data conflictsUsername changed on two devices simultaneouslyLast-Write-Wins with timestamp
Group membershipUser added and removed concurrentlyTombstone + rejoins require re-add

Resolution Strategy

Zentalk uses Last-Write-Wins (LWW) with vector clocks for conflict resolution:

Vector Clock Structure: ┌─────────────────────────────────────────┐ │ { device_id: counter } │ │ │ │ Phone: { phone: 5, desktop: 3 } │ │ Desktop: { phone: 4, desktop: 4 } │ │ │ │ Conflict detected: Neither dominates │ └─────────────────────────────────────────┘

Timestamp Usage:

ComponentPurpose
Lamport timestampLogical ordering of events
Wall clockTie-breaking when vector clocks equal
Device IDFinal tie-breaker (deterministic)

Tie-Breaking Rules:

1. Compare vector clocks - If V1 > V2: V1 wins - If V2 > V1: V2 wins - If concurrent: proceed to step 2 2. Compare wall-clock timestamps - Higher timestamp wins - If equal: proceed to step 3 3. Compare device IDs (lexicographic) - Higher device ID wins - Deterministic, reproducible on all devices

Message Ordering

Messages maintain causal ordering guarantees even across multiple devices:

Causal Ordering Guarantees:

GuaranteeDescription
Send orderMessages from same device delivered in send order
Causal deliveryIf A causes B, A delivered before B
No guaranteesConcurrent messages may arrive in any order

Happens-Before Relationship:

Event A happens-before Event B if: 1. A and B on same device, A sent first 2. A is send, B is corresponding receive 3. Transitive: A→C and C→B implies A→B

Double Ratchet Counter Ordering:

Double Ratchet Message Keys: ┌─────────────────────────────────────────┐ │ Chain Key (n) → Message Key (n) │ │ ↓ │ │ Chain Key (n+1) → Message Key (n+1) │ │ ↓ │ │ Chain Key (n+2) → Message Key (n+2) │ └─────────────────────────────────────────┘ Counter (n) provides strict ordering per session. Out-of-order messages buffered until gap filled.

Sync Protocol

Devices discover and resolve out-of-sync state through the following protocol:

Sync Discovery:

MethodDescription
HeartbeatPeriodic vector clock exchange (every 30s when online)
On-connectFull sync check when device comes online
Push notificationImmediate sync trigger on state change

Pull vs Push Synchronization:

Push Sync (real-time): Device A modifies state Encrypt delta with self-sync key Send to all linked devices Devices apply delta immediately Pull Sync (reconnection): Device comes online Send vector clock to sync service Receive list of missing updates Fetch and apply in causal order

Merkle Tree for Efficient Diff Detection:

Merkle Tree Structure: Root Hash / \ Hash(A-M) Hash(N-Z) / \ / \ Hash(A-F) Hash(G-M) ... ... | Contact entries Sync process: 1. Exchange root hashes 2. If match: fully synced 3. If mismatch: descend tree 4. Identify changed subtrees only 5. Transfer only divergent data

Edge Cases

ScenarioHandling
Device offline for weeksFull sync on reconnect, may require message re-fetch
Sync message lostRetry with exponential backoff, fallback to pull sync
Maximum divergenceAfter 1000 unsynced operations, force full state reconciliation
Clock significantly wrongReject updates with timestamps >24h in future
Conflicting deletesTombstones persist for 30 days to prevent resurrection

Offline Device Recovery:

1. Device reconnects after extended offline period 2. Compare local vector clock with server state 3. If divergence < threshold (1000 ops): - Incremental sync via Merkle tree diff 4. If divergence >= threshold: - Full state download required - Local-only changes merged with conflict resolution 5. Message history: - Fetch missing messages by timestamp range - Double Ratchet sessions renegotiated if needed

Lost Sync Message Handling:

1. Sync message sent with sequence number 2. Recipient acknowledges receipt 3. If no ACK within timeout (30s): - Retry up to 3 times with exponential backoff 4. If all retries fail: - Mark device as potentially stale - Next heartbeat triggers full sync check 5. Idempotent operations prevent duplicate application

Device Removal

Voluntary Removal

1. User initiates removal from primary device 2. Primary sends revocation to: - Server (remove device registration) - Other linked devices (update device list) 3. Contacts notified of device change (optional) 4. Sessions with removed device marked stale

Remote Wipe

ActionEffect
Revoke deviceRemove from server, invalidate keys
Wipe dataClear local storage on target device
Notify contactsAlert to potential compromise

Lost Device

1. User logs into remaining device (or recovers via backup) 2. Marks lost device as compromised 3. Rotates all session keys 4. Server removes lost device's registration 5. New sessions established with contacts

Backup & Recovery

Encrypted Backup

DataBackup Method
Identity KeyMesh storage (PBKDF2 + AES-256-GCM)
Device KeysNot backed up (regenerated)
Message historyOptional encrypted backup
Contact listMesh storage

Recovery Process

1. User enters recovery passphrase 2. Fetch encrypted backup from mesh 3. Derive key: K = PBKDF2(passphrase, salt, 600000) 4. Decrypt Identity Key 5. Generate new Device Key for this device 6. Re-establish sessions with contacts

Recovery Code

12-word mnemonic for account recovery:

1. BIP-39 word list 2. Encodes 128 bits of entropy 3. Used as PBKDF2 input 4. Stored securely by user (offline)

Security Considerations

Device Compromise

ScenarioImpactMitigation
One device compromisedThat device’s sessions exposedRevoke + rotate
All devices compromisedAccount compromisedRecovery required
Backup compromisedIdentity Key exposedStrong passphrase

Identity Key Protection

ProtectionImplementation
Local encryptionAES-256-GCM + device key
PIN/BiometricRequired to decrypt
Secure enclaveUsed where available (iOS/Android)

Device Limits

ParameterValue
Max linked devices5
Device inactivity timeout90 days
Session reestablishmentAutomatic
Key bundle refreshWeekly

Device Revocation & Key Rotation

This section provides detailed technical documentation on revoking devices, rotating cryptographic keys, and handling emergency scenarios that require identity reset.

When to Revoke a Device

Device revocation should be performed promptly in any of the following situations:

ScenarioUrgencyRecommended Action
Device lost or stolenCriticalImmediate revocation + key rotation
Device compromised (malware, root access)CriticalImmediate revocation + key rotation
Selling or giving away deviceHighRevoke before transfer, verify data wipe
Suspicious activity detectedHighRevoke and investigate
Device no longer usedLowRevoke at convenience
Device hardware failureLowRevoke to clean up device list

Indicators of Suspicious Activity:

IndicatorDescription
Unknown sessionsSessions appearing that user did not initiate
Unexpected read receiptsMessages marked read when device was offline
Contact reportsContacts receiving messages user did not send
Authentication anomaliesLogin attempts from unknown locations
Key verification failuresSafety number changes not initiated by user

Device Revocation Process

Standard Revocation (From Another Device)

Revocation from Trusted Device: 1. User authenticates on remaining trusted device - Biometric or PIN verification required - Rate limited: max 3 attempts per hour 2. Select device to revoke from device list - Device identified by: name, last seen, device ID prefix - Confirmation required with explicit device name 3. Generate revocation certificate RevokeCert = Sign(IK_priv, { device_id: target_device_id, timestamp: current_time, reason: revocation_reason, initiator: revoking_device_id }) 4. Submit to server - Server validates signature against Identity Key - Server validates initiator is registered device - Revocation recorded with timestamp 5. Propagate to network - Other linked devices notified immediately - Contact key servers updated - Prekey bundles invalidated

Emergency Revocation (Via Recovery Phrase)

When no trusted device is available:

Recovery-Based Revocation: 1. User enters 12-word recovery phrase - Derives Identity Key: IK = KDF(mnemonic, "identity") - No device access required 2. Authenticate to revocation service - Challenge-response using derived IK - Additional verification (email/SMS if configured) 3. Select revocation scope - Single device revocation - All devices revocation (nuclear option) 4. Generate emergency revocation certificate EmergencyRevokeCert = Sign(IK_priv, { scope: "single" | "all", device_ids: [target_devices], timestamp: current_time, emergency: true }) 5. Execute revocation - All selected devices immediately invalidated - Sessions terminated server-side - User must re-register at least one device

Server-Side Device List Update

StepActionTiming
1Validate revocation certificateImmediate
2Remove device from account device listImmediate
3Invalidate device prekey bundleImmediate
4Mark active sessions as terminatedImmediate
5Update device count for accountImmediate
6Queue notifications to contactsWithin 1 second
7Purge cached device informationWithin 5 seconds

Contact Notification

Contacts are notified of device changes to maintain security awareness:

Notification TypeTriggerContent
Device removedStandard revocationDevice count changed
Security alertEmergency revocationPotential compromise warning
Key changeIdentity rotationSafety number changed
Contact Notification Message: NotifyMsg = Encrypt(session_key, { type: "device_change", event: "revocation", device_count: new_count, timestamp: revocation_time, requires_verification: boolean }) - Sent to all active contacts - Delivered to all their devices - UI displays security notification

What Happens on Revocation

Session Key Invalidation

ComponentState BeforeState After
Device signing keyValid, trustedInvalid, untrusted
Double Ratchet sessionsActiveTerminated
Message keys (unused)CachedDeleted server-side
Sender keys (groups)DistributedInvalidated
Session Invalidation Process: 1. Server marks device sessions as revoked session.status = "revoked" session.revoked_at = timestamp 2. Pending messages for device - Messages in queue: deleted - Messages in transit: delivery fails 3. Session ratchet state - Server cannot access (E2EE) - Other devices: remove peer session - Contacts: session marked stale

Prekey Removal

Prekey TypeActionTiming
Signed prekeyDeleted from serverImmediate
One-time prekeysAll deletedImmediate
Last-resort prekeyDeletedImmediate

New sessions cannot be established with revoked device as no prekeys are available.

Message Routing Changes

Message Routing After Revocation: Before (3 devices): Sender → Server → [Device A, Device B, Device C] After Device C revoked (2 devices): Sender → Server → [Device A, Device B] Server behavior: - Device C removed from routing table - Messages encrypted for Device C: rejected at send time - Senders fetching device list: Device C excluded

Local Data on Revoked Device

Data TypeStatusUser Action Required
Private keysStill present locallyManual wipe recommended
Message historyStill present locallyManual wipe recommended
Contact listStill present locallyManual wipe recommended
Session stateOrphaned (server rejected)No action needed

Important: Revocation prevents network access but does not remotely wipe local data. For lost/stolen devices, assume local data is compromised.

Local Data State Post-Revocation: Revoked device attempts operation: Send message → Server rejects (device not registered) Fetch messages → Server rejects (invalid device) Refresh prekeys → Server rejects (device revoked) Device cannot: - Send or receive new messages - Establish new sessions - Access account resources Device retains: - Previously decrypted messages - Contact information - Private key material (until wiped)

Identity Key Rotation

Identity Key rotation is a significant security operation that resets the cryptographic root of trust for an account.

When Rotation Is Necessary

ScenarioRotation RequiredRationale
Device compromise suspectedYesAttacker may have Identity Key
Recovery phrase compromisedYesAttacker can derive Identity Key
All devices lost simultaneouslyYesCannot prove continuity
Extended absence from platformOptionalProactive security measure
Normal device addition/removalNoDevice keys are separate

Rotation Procedure

Identity Key Rotation Protocol: 1. Generate new Identity Key pair IK_new = Ed25519_KeyGen() 2. Create rotation certificate (signed by old key) RotationCert = Sign(IK_old_priv, { old_identity: IK_old_pub, new_identity: IK_new_pub, timestamp: current_time, reason: rotation_reason }) 3. Submit rotation to server - Server validates old key signature - Server validates user authentication - Atomic update: old key → new key 4. Update all device keys For each linked device: DK_new = Ed25519_KeyGen() DeviceCert = Sign(IK_new_priv, DK_new_pub) Upload new prekey bundle 5. Notify contacts of key change - Safety numbers invalidated - Re-verification required

Impact on Existing Sessions

Session TypeImpactRecovery
1:1 conversationsAll sessions invalidatedAutomatic renegotiation
Group conversationsSender keys invalidatedNew sender key distribution
Pending messagesMay be lostRe-send required
Session Renegotiation After Rotation: 1. Contact receives rotation notification - Old safety number marked invalid - New safety number computed 2. Next message triggers X3DH - Fetches new prekey bundle (new Identity Key) - Establishes fresh Double Ratchet session 3. Both parties see verification prompt - "Safety number changed" - Manual verification recommended

Contact Re-verification

Verification MethodProcess
Safety number comparisonCompare 60-digit number or QR code
In-person verificationScan QR codes on each other’s devices
Trusted introducerMutual contact vouches for identity
Safety Number Computation: SafetyNumber = Truncate( SHA-256( Sort(IK_A_pub, IK_B_pub) || Sort(UserID_A, UserID_B) ), 30 bytes ) Displayed as: 60 digits in groups of 5 Example: 12345 67890 12345 67890 12345 67890 ... Any Identity Key change → New safety number

Emergency Account Reset

Complete account reset destroys all cryptographic continuity and starts fresh.

When Emergency Reset Is Appropriate

SituationReset AppropriateAlternative
All devices lost, no recovery phraseYesNone
Recovery phrase compromisedYesRotation if devices available
Targeted by sophisticated attackerYesRotation may suffice
Voluntary fresh startYesUser preference
Single device compromiseNoRevocation + rotation

Reset Procedure

Emergency Account Reset: 1. Authenticate identity - Phone number verification - Email verification (if configured) - Waiting period (24-72 hours) for abuse prevention 2. Server-side cleanup - All devices deregistered - All prekey bundles deleted - Account metadata purged - Message queues cleared 3. Generate new identity IK_new = Ed25519_KeyGen() - No cryptographic link to old identity - Old safety numbers permanently invalid 4. Re-register account - New device registered - New prekey bundle uploaded - Account operational 5. Contact implications - All contacts see "new user" warning - No automatic session continuity - Manual re-verification required for all

Loss of Message History

Data TypeStatus After Reset
Server-stored messagesPermanently deleted
Local message historyLost (no device access)
Contact listMust be rebuilt
Group membershipsMust be re-invited
Verification statusAll reset to unverified

Warning: Emergency reset is irreversible. All message history is permanently lost.

Re-establishing Contacts

Contact Re-establishment: After reset, contacts see: "This contact has reset their account" "Verify their identity before continuing" Re-establishment process: 1. Reset user sends message to contact 2. Contact receives with warning banner 3. X3DH establishes new session (no history) 4. Both parties should verify safety numbers 5. Previous conversation: inaccessible

Revocation Propagation

How Revocation Spreads Through Network

Revocation Propagation Flow: T+0ms: User initiates revocation T+10ms: Server validates and records T+50ms: Server updates device registry T+100ms: Push notification to linked devices T+100ms: Revocation logged to audit trail T+500ms: Contact key servers updated T+1000ms: Active contacts notified (online) T+varies: Offline contacts notified on reconnect
Propagation TargetMethodLatency
Linked devicesPush notification< 1 second
Online contactsReal-time message< 2 seconds
Offline contactsQueued notificationOn reconnect
Key distribution serversDirect update< 1 second

Timing Guarantees

GuaranteeSLAMechanism
Device registry update< 100msSynchronous database write
Prekey invalidation< 100msSynchronous deletion
Linked device notification< 5 secondsPush with retry
Contact notification (online)< 10 secondsMessage queue
Contact notification (offline)On reconnectPersistent queue
Timing Guarantees Detail: Hard guarantees: - Device cannot authenticate after: 100ms - Prekeys unavailable after: 100ms - New sessions impossible after: 100ms Soft guarantees (best effort): - Linked device UI update: typically < 5s - Contact notification delivery: typically < 10s - Full network propagation: typically < 60s

Handling Offline Contacts

Contact StateHandling
OnlineImmediate push notification
Offline < 24hNotification queued, delivered on reconnect
Offline > 24hNotification queued + email alert (if configured)
Offline > 30dSession marked stale, re-establish on reconnect
Offline Contact Notification: 1. Server queues revocation notification Queue entry: { recipient: contact_id, type: "device_revoked", payload: encrypted_notification, created_at: timestamp, expires_at: timestamp + 30d } 2. Contact comes online - Fetches queued notifications - Processes revocation notice - Updates local session state 3. Contact's next message to user - Fetches fresh device list (revoked device excluded) - Encrypts only for valid devices

Security Considerations

Preventing Unauthorized Revocation

ThreatMitigation
Attacker with stolen deviceRequires device unlock (PIN/biometric)
Attacker with recovery phraseAdditional verification for emergency revocation
Server compromiseRevocation requires valid signature from Identity Key
MITM attackRevocation certificate cryptographically signed
Revocation Authentication Chain: Device-initiated revocation: 1. Device unlock (biometric/PIN) 2. In-app authentication 3. Confirmation prompt with device name 4. Cryptographic signature with Device Key 5. Server validates against registered keys Recovery-initiated revocation: 1. Recovery phrase verification 2. Secondary factor (email/SMS) 3. Time delay (configurable, default 1 hour) 4. Cryptographic signature with derived key 5. Server validates + logs for audit

Authentication Requirements for Revocation Actions

ActionAuthentication Required
View device listDevice unlock
Revoke other deviceDevice unlock + confirmation
Revoke own deviceDevice unlock + explicit consent
Emergency revoke allRecovery phrase + secondary factor + time delay
Identity rotationDevice unlock + confirmation + contact notification
Account resetIdentity verification + waiting period
Authentication Escalation: Level 1 - View only: Requirement: Device unlock Allows: View device list, activity Level 2 - Single device action: Requirement: Device unlock + confirmation Allows: Revoke one device Level 3 - Account-wide action: Requirement: Recovery phrase + secondary factor Allows: Revoke all, rotate identity Level 4 - Destructive action: Requirement: Full verification + waiting period Allows: Account reset

Revocation Finality

PropertyDescription
IrreversibleRevocation cannot be undone
Immediate effectNetwork access terminated instantly
Cryptographic proofSigned certificate stored permanently
Audit trailAll revocations logged with metadata
Revocation Finality Properties: Once revoked: - Device ID permanently blacklisted for account - Same device can re-register as NEW device only - Original sessions cannot be restored - Original prekeys cannot be recovered Re-linking a revoked physical device: 1. Device must be wiped/reset 2. Fresh device key generated 3. New linking process required 4. No session continuity from before revocation 5. New device ID assigned

Revocation Audit Trail

FieldDescription
TimestampExact time of revocation
InitiatorDevice or recovery method that initiated
TargetDevice(s) revoked
ReasonUser-provided or system-determined reason
CertificateCryptographic proof of authorization
Audit Record Structure: AuditRecord = { event_id: UUID, timestamp: ISO8601, event_type: "device_revocation", account_id: hashed_identifier, initiator: { type: "device" | "recovery" | "admin", device_id: initiator_id (if device), ip_hash: SHA256(ip_address) }, target: { device_id: revoked_device_id, device_name_hash: SHA256(device_name) }, reason: enum(lost, stolen, compromised, sold, other), certificate: base64(signed_revocation_cert), propagation: { linked_devices_notified: count, contacts_notified: count, completion_time_ms: duration } } Retention: 2 years minimum Access: User can request own audit log
Last updated on