Device Linking Sequence

Interaction Type: 🤝 IN-PERSON (Proximity Required)

User links a new device to their existing identity. The new device receives the master seed and syncs all data. A confirmation code and proximity verification prevent unauthorized remote linking.

Participants

  • User - Person owning both devices
  • Device A (Primary) - Existing device with identity
  • Device B (New) - New device to be linked

Sequence Diagram

┌──────┐                                    ┌────────────────────┐         ┌────────────────┐                                                                
│ User │                                    │ Device A (Primary) │         │ Device B (New) │                                                                
└───┬──┘                                    └──────────┬─────────┘         └────────┬───────┘                                                                
    │                                                  │                            │                                                                        
    │      Settings > Devices > Link New Device        │                            │                                                                        
    │──────────────────────────────────────────────────▶                            │                                                                        
    │                                                  │                            │                                                                        
    │                                                  ├───┐                        │                                                                        
    │                                                  │   │ Generate ephemeral link_key (32 bytes)                                                          
    │                                                  ◀───┘                        │                                                                        
    │                                                  │                            │                                                                        
    │                                                  ├───┐                        │                                                                        
    │                                                  │   │ Sign QR fields with identity Ed25519 key                                                        
    │                                                  ◀───┘                        │                                                                        
    │                                                  │                            │                                                                        
    │                                                  ├───┐                        │                                                                        
    │                                                  │   │ Create QR: WBDL | version | identity_pubkey | link_key | timestamp | signature                  
    │                                                  ◀───┘                        │                                                                        
    │                                                  │                            │                                                                        
    │     Display QR code (expires in 5 minutes)       │                            │                                                                        
    ◀──────────────────────────────────────────────────│                            │                                                                        
    │                                                  │                            │                                                                        
    │                           Link to Existing Identity                           │                                                                        
    │───────────────────────────────────────────────────────────────────────────────▶                                                                        
    │                                                  │                            │                                                                        
    │                                                  │                            ├───┐                                                                    
    │                                                  │                            │   │ Scan QR code from Device A                                         
    │                                                  │                            ◀───┘                                                                    
    │                                                  │                            │                                                                        
    │                                                  │                            ├───┐                                                                    
    │                                                  │                            │   │ Validate WBDL magic, version, signature, expiry                    
    │                                                  │                            ◀───┘                                                                    
    │                                                  │                            │                                                                        
    │                                                  │                            ├───┐                                                                    
    │                                                  │                            │   │ Create DeviceLinkRequest (device_name, random nonce, timestamp)    
    │                                                  │                            ◀───┘                                                                    
    │                                                  │                            │                                                                        
    │                                                  │                            ├───┐                                                                    
    │                                                  │                            │   │ Encrypt request with link_key (ChaCha20-Poly1305)                  
    │                                                  │                            ◀───┘                                                                    
    │                                                  │                            │                                                                        
    │                                                  │  Send encrypted request    │                                                                        
    │                                                  ◀────────────────────────────│                                                                        
    │                                                  │                            │                                                                        
    │                                            ┌───────────────────────────────────────┐                                                                   
    │                                            │ CONFIRMATION & PROXIMITY VERIFICATION │                                                                   
    │                                            └───────────────────────────────────────┘                                                                   
    │                                                  │                            │                                                                        
    │                                                  ├───┐                        │                                                                        
    │                                                  │   │ Decrypt request using link_key                                                                  
    │                                                  ◀───┘                        │                                                                        
    │                                                  │                            │                                                                        
    │                                                  ├───┐                        │                                                                        
    │                                                  │   │ Derive confirmation code: HMAC-SHA256(link_key, nonce) → XXX-XXX                                
    │                                                  ◀───┘                        │                                                                        
    │                                                  │                            │                                                                        
    │  Show: "Link device 'Device B'? Code: XXX-XXX"   │                            │                                                                        
    ◀──────────────────────────────────────────────────│                            │                                                                        
    │                                                  │                            │                                                                        
    │                                                  │                            ├───┐                                                                    
    │                                                  │                            │   │ Derive same confirmation code from link_key + nonce                
    │                                                  │                            ◀───┘                                                                    
    │                                                  │                            │                                                                        
    │                      Show: "Confirmation code: XXX-XXX"                       │                                                                        
    ◀───────────────────────────────────────────────────────────────────────────────│                                                                        
    │                                                  │                            │                                                                        
    ├───┐                                              │                            │                                                                        
    │   │ Verify codes match on both screens           │                            │                                                                        
    ◀───┘                                              │                            │                                                                        
    │                                                  │                            │                                                                        
    │                  Confirm link                    │                            │                                                                        
    │──────────────────────────────────────────────────▶                            │                                                                        
    │                                                  │                            │                                                                        
    │                                                  ├───┐                        │                                                                        
    │                                                  │   │ Set proximity verified │                                                                        
    │                                                  ◀───┘                        │                                                                        
    │                                                  │                            │                                                                        
    │                                                  │   ┌───────────────────┐    │                                                                        
    │                                                  │   │ IDENTITY TRANSFER │    │                                                                        
    │                                                  │   └───────────────────┘    │                                                                        
    │                                                  │                            │                                                                        
    │                                                  ├───┐                        │                                                                        
    │                                                  │   │ Derive new device keys from master_seed + device_index                                          
    │                                                  ◀───┘                        │                                                                        
    │                                                  │                            │                                                                        
    │                                                  ├───┐                        │                                                                        
    │                                                  │   │ Add Device B to registry, re-sign                                                               
    │                                                  ◀───┘                        │                                                                        
    │                                                  │                            │                                                                        
    │                                                  ├───┐                        │                                                                        
    │                                                  │   │ Build response: master_seed + display_name + device_index + registry + sync_payload             
    │                                                  ◀───┘                        │                                                                        
    │                                                  │                            │                                                                        
    │                                                  ├───┐                        │                                                                        
    │                                                  │   │ Encrypt response with link_key (ChaCha20-Poly1305)                                              
    │                                                  ◀───┘                        │                                                                        
    │                                                  │                            │                                                                        
    │                                                  │  Send encrypted response   │                                                                        
    │                                                  │────────────────────────────▶                                                                        
    │                                                  │                            │                                                                        
    │                                                  │                            ├───┐                                                                    
    │                                                  │                            │   │ Decrypt response                                                   
    │                                                  │                            ◀───┘                                                                    
    │                                                  │                            │                                                                        
    │                                                  │                            ├───┐                                                                    
    │                                                  │                            │   │ Extract master_seed, registry, sync_payload                        
    │                                                  │                            ◀───┘                                                                    
    │                                                  │                            │                                                                        
    │                                                  │                            ├───┐                                                                    
    │                                                  │                            │   │ Derive own device keys from master_seed + device_index             
    │                                                  │                            ◀───┘                                                                    
    │                                                  │                            │                                                                        
    │                                                  │                            ├───┐                                                                    
    │                                                  │                            │   │ Store identity locally                                             
    │                                                  │                            ◀───┘                                                                    
    │                                                  │                            │                                                                        
    │                                                  │                            ├───┐                                                                    
    │                                                  │                            │   │ Apply sync payload (contacts, card)                                
    │                                                  │                            ◀───┘                                                                    
    │                                                  │                            │                                                                        
    │          Device B linked successfully            │                            │                                                                        
    ◀──────────────────────────────────────────────────│                            │                                                                        
    │                                                  │                            │                                                                        
    │                           Welcome back, [Your Name]                           │                                                                        
    ◀───────────────────────────────────────────────────────────────────────────────│                                                                        
    │                                                  │                            │                                                                        
    │                                          ┌──────────────────────────────────────────┐                                                                  
    │                                          │ Both devices now share the same identity │                                                                  
    │                                          └──────────────────────────────────────────┘                                                                  
    │                                                  │                            │                                                                        
┌───┴──┐                                    ┌──────────┴─────────┐         ┌────────┴───────┐                                                                
│ User │                                    │ Device A (Primary) │         │ Device B (New) │                                                                
└──────┘                                    └────────────────────┘         └────────────────┘                                                                

Data Exchanged

Binary format with WBDL magic bytes, base64-encoded for QR:

WBDL              (4 bytes magic)
version           (1 byte, currently 1)
identity_pubkey   (32 bytes, Ed25519 public key)
link_key          (32 bytes, random ephemeral key)
timestamp         (8 bytes, big-endian u64 unix seconds)
signature         (64 bytes, Ed25519 over all preceding fields)
─────────────────
Total: 141 bytes  (before base64 encoding)

The QR expires after 300 seconds (5 minutes). Signature is verified by the new device using the embedded identity public key.

Confirmation Code

Derived independently by both devices:

HMAC-SHA256(link_key, request_nonce)
  → first 4 bytes as big-endian u32
  → modulo 1,000,000
  → formatted as XXX-XXX

Both devices display the same code. User verifies they match.

Proximity Challenge

For external proximity verification (NFC, ultrasonic, etc.):

HKDF(ikm=link_key, info="vauchi-device-link-proximity-v1", len=16)
  → 16-byte challenge

Both devices derive the same challenge from the shared link key.

DeviceLinkRequest (New → Existing)

Encrypted with ChaCha20-Poly1305 using link_key:

device_name_len   (4 bytes, little-endian u32)
device_name       (variable, UTF-8)
nonce             (32 bytes, random)
timestamp         (8 bytes, little-endian u64)

DeviceLinkResponse (Existing → New)

Encrypted with ChaCha20-Poly1305 using link_key:

master_seed       (32 bytes, zeroized after use)
display_name_len  (4 bytes, little-endian u32)
display_name      (variable, UTF-8)
device_index      (4 bytes, little-endian u32)
registry_json_len (4 bytes, little-endian u32)
registry_json     (variable, signed DeviceRegistry)
sync_payload_len  (4 bytes, little-endian u32)
sync_payload_json (variable, contacts + card)

Security Properties

PropertyMechanism
Seed EncryptionChaCha20-Poly1305 with ephemeral link_key
QR AuthenticationEd25519 signature over QR fields
Confirmation CodeHMAC-SHA256(link_key, nonce) displayed on both devices
Proximity VerificationHKDF-derived 16-byte challenge; enforced before confirm
Replay PreventionRandom 32-byte nonce in each request
Token ExpiryQR expires after 5 minutes
Registry IntegrityEd25519 signature over version + device list
Memory SafetyMaster seed zeroized on Drop
Device LimitMaximum 10 devices per identity

Numeric Code Fallback (No Camera)

┌──────┐                      ┌──────────┐            ┌────────────────────────┐                                         
│ User │                      │ Device A │            │ Device B (Desktop/CLI) │                                         
└───┬──┘                      └─────┬────┘            └────────────┬───────────┘                                         
    │                               │                              │                                                     
    │      Generate link code       │                              │                                                     
    │───────────────────────────────▶                              │                                                     
    │                               │                              │                                                     
    │  Show QR code + data string   │                              │                                                     
    ◀───────────────────────────────│                              │                                                     
    │                               │                              │                                                     
    │                  Link to Existing Identity                   │                                                     
    │──────────────────────────────────────────────────────────────▶                                                     
    │                               │                              │                                                     
    │               Paste data string from Device A                │                                                     
    │──────────────────────────────────────────────────────────────▶                                                     
    │                               │                              │                                                     
    │                               │                              ├───┐                                                 
    │                               │                              │   │ Parse WBDL data, validate signature + expiry    
    │                               │                              ◀───┘                                                 
    │                               │                              │                                                     
    │                          ┌──────────────────────────────────────┐                                                  
    │                          │ Same confirmation code flow as above │                                                  
    │                          └──────────────────────────────────────┘                                                  
    │                               │                              │                                                     
    │         Code: XXX-XXX         │                              │                                                     
    ◀───────────────────────────────│                              │                                                     
    │                               │                              │                                                     
    │                        Code: XXX-XXX                         │                                                     
    ◀──────────────────────────────────────────────────────────────│                                                     
    │                               │                              │                                                     
    │            Confirm            │                              │                                                     
    │───────────────────────────────▶                              │                                                     
    │                               │                              │                                                     
    │                               │  Encrypted identity bundle   │                                                     
    │                               │──────────────────────────────▶                                                     
    │                               │                              │                                                     
    │                               │                              ├───┐                                                 
    │                               │                              │   │ Complete linking                                
    │                               │                              ◀───┘                                                 
    │                               │                              │                                                     
┌───┴──┐                      ┌─────┴────┐            ┌────────────┴───────────┐                                         
│ User │                      │ Device A │            │ Device B (Desktop/CLI) │                                         
└──────┘                      └──────────┘            └────────────────────────┘                                         

Revoking a Device

┌──────┐                                ┌──────────┐         ┌──────────┐              ┌───────┐      
│ User │                                │ Device A │         │ Device B │              │ Relay │      
└───┬──┘                                └─────┬────┘         └─────┬────┘              └───┬───┘      
    │                                         │                    │                       │          
    │  Settings > Devices > Revoke Device B   │                    │                       │          
    │─────────────────────────────────────────▶                    │                       │          
    │                                         │                    │                       │          
    │           Confirm revocation            │                    │                       │          
    │─────────────────────────────────────────▶                    │                       │          
    │                                         │                    │                       │          
    │                                         ├───┐                │                       │          
    │                                         │   │ Mark Device B as revoked in registry   │          
    │                                         ◀───┘                │                       │          
    │                                         │                    │                       │          
    │                                         ├───┐                │                       │          
    │                                         │   │ Re-sign registry with identity key     │          
    │                                         ◀───┘                │                       │          
    │                                         │                    │                       │          
    │                                         ├───┐                │                       │          
    │                                         │   │ Increment registry version             │          
    │                                         ◀───┘                │                       │          
    │                                         │                    │                       │          
    │                                         │     Push updated registry (encrypted)      │          
    │                                         │────────────────────────────────────────────▶          
    │                                         │                    │                       │          
    │                                         │                    │  Forward revocation   │          
    │                                         │                    ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│          
    │                                         │                    │                       │          
    │                                         │                    ├───┐                   │          
    │                                         │                    │   │ Receive revocation notice    
    │                                         │                    ◀───┘                   │          
    │                                         │                    │                       │          
    │                                         │                    ├───┐                   │          
    │                                         │                    │   │ Wipe all identity data       
    │                                         │                    ◀───┘                   │          
    │                                         │                    │                       │          
    │                                         │                    ├───┐                   │          
    │                                         │                    │   │ Return to welcome screen     
    │                                         │                    ◀───┘                   │          
    │                                         │                    │                       │          
    │            Device B revoked             │                    │                       │          
    ◀─────────────────────────────────────────│                    │                       │          
    │                                         │                    │                       │          
    │                This device has been unlinked                 │                       │          
    ◀──────────────────────────────────────────────────────────────│                       │          
    │                                         │                    │                       │          
┌───┴──┐                                ┌─────┴────┐         ┌─────┴────┐              ┌───┴───┐      
│ User │                                │ Device A │         │ Device B │              │ Relay │      
└──────┘                                └──────────┘         └──────────┘              └───────┘      

Platform Implementation Status

PlatformStatusNotes
Core APICompleteFull protocol with tests
CLIComplete7 commands: list, link, join, complete, finish, revoke, info
Desktop (native)CompleteNative UI (SwiftUI/GTK/Qt) with QR display, confirmation overlay
TUICompleteratatui UI with QR overlay, vim-style navigation
iOSPlannedAwaiting mobile bindings
AndroidPlannedAwaiting mobile bindings