From 0be35a53780711166d99290693e7eaf150b2126a Mon Sep 17 00:00:00 2001 From: jack Date: Tue, 22 Jul 2025 11:01:24 +0200 Subject: [PATCH] Fix Noise session persistence during peer ID rotation - Add session migration when peer IDs rotate - Sessions now follow peers across ID changes via fingerprint - Add migratePeerSession to NoiseEncryptionService - Add migrateSession to NoiseSessionManager - Integrate migration in BluetoothMeshService updatePeerBinding This fixes the issue where established Noise sessions were lost when peer IDs rotated, causing "No Noise session" errors and requiring re-handshake. --- bitchat/Noise/NoiseSession.swift | 13 +++++++++++++ bitchat/Services/BluetoothMeshService.swift | 3 +++ bitchat/Services/NoiseEncryptionService.swift | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/bitchat/Noise/NoiseSession.swift b/bitchat/Noise/NoiseSession.swift index 973b6fa8..da873cb9 100644 --- a/bitchat/Noise/NoiseSession.swift +++ b/bitchat/Noise/NoiseSession.swift @@ -259,6 +259,19 @@ class NoiseSessionManager { } } + func migrateSession(from oldPeerID: String, to newPeerID: String) { + _ = managerQueue.sync(flags: .barrier) { + // Check if we have a session for the old peer ID + if let session = sessions[oldPeerID] { + // Move the session to the new peer ID + sessions[newPeerID] = session + sessions.removeValue(forKey: oldPeerID) + + SecurityLogger.log("Migrated Noise session from \(oldPeerID) to \(newPeerID)", category: SecurityLogger.noise, level: .info) + } + } + } + func getEstablishedSessions() -> [String: NoiseSession] { return managerQueue.sync { return sessions.filter { $0.value.isEstablished() } diff --git a/bitchat/Services/BluetoothMeshService.swift b/bitchat/Services/BluetoothMeshService.swift index 2663a2bd..29a9f0a5 100644 --- a/bitchat/Services/BluetoothMeshService.swift +++ b/bitchat/Services/BluetoothMeshService.swift @@ -364,6 +364,9 @@ class BluetoothMeshService: NSObject { // Notify about the change if it's a rotation if let oldID = oldPeerID { + // Migrate Noise session to new peer ID + self.noiseService.migratePeerSession(from: oldID, to: newPeerID, fingerprint: fingerprint) + self.notifyPeerIDChange(oldPeerID: oldID, newPeerID: newPeerID, fingerprint: fingerprint) } } diff --git a/bitchat/Services/NoiseEncryptionService.swift b/bitchat/Services/NoiseEncryptionService.swift index 99994558..79f7190a 100644 --- a/bitchat/Services/NoiseEncryptionService.swift +++ b/bitchat/Services/NoiseEncryptionService.swift @@ -279,6 +279,24 @@ class NoiseEncryptionService { } } + /// Migrate session when peer ID changes + func migratePeerSession(from oldPeerID: String, to newPeerID: String, fingerprint: String) { + // First update the fingerprint mappings + serviceQueue.sync(flags: .barrier) { + // Remove old mapping + if let oldFingerprint = peerFingerprints[oldPeerID], oldFingerprint == fingerprint { + peerFingerprints.removeValue(forKey: oldPeerID) + } + + // Add new mapping + peerFingerprints[newPeerID] = fingerprint + fingerprintToPeerID[fingerprint] = newPeerID + } + + // Migrate the session in session manager + sessionManager.migrateSession(from: oldPeerID, to: newPeerID) + } + // MARK: - Private Helpers private func handleSessionEstablished(peerID: String, remoteStaticKey: Curve25519.KeyAgreement.PublicKey) {