From fb35d59dc9249019cdabc549e52c07b96a39fe18 Mon Sep 17 00:00:00 2001 From: jack Date: Wed, 23 Jul 2025 10:35:13 +0200 Subject: [PATCH] Fix session migration state mismatch after peer restart When a peer restarts and gets a new peer ID, the session migration was only happening on one side, causing a state mismatch where one peer had an encrypted session but the other didn't. Changed approach to clear the old session instead of migrating it, ensuring both peers establish a fresh handshake after ID rotation. This fixes the issue where one peer shows empty lock (no encryption) while the other shows lock with circle (encryption established). --- bitchat.xcodeproj/project.pbxproj | 6 ++++++ bitchat/Services/BluetoothMeshService.swift | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/bitchat.xcodeproj/project.pbxproj b/bitchat.xcodeproj/project.pbxproj index 76227d63..a598a611 100644 --- a/bitchat.xcodeproj/project.pbxproj +++ b/bitchat.xcodeproj/project.pbxproj @@ -30,6 +30,8 @@ 04636BE02E30BE5100FBCFA8 /* PublicChatE2ETests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04636BC52E30BE5100FBCFA8 /* PublicChatE2ETests.swift */; }; 04636BE82E30BEC600FBCFA8 /* IntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04636BE12E30BEC600FBCFA8 /* IntegrationTests.swift */; }; 04636BEB2E30BEC600FBCFA8 /* IntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04636BE12E30BEC600FBCFA8 /* IntegrationTests.swift */; }; + 04636BED2E30CD4A00FBCFA8 /* NoiseHandshakeCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04636BEC2E30CD4A00FBCFA8 /* NoiseHandshakeCoordinator.swift */; }; + 04636BEE2E30CD4A00FBCFA8 /* NoiseHandshakeCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04636BEC2E30CD4A00FBCFA8 /* NoiseHandshakeCoordinator.swift */; }; 04891CA92E22971E0064A111 /* LRUCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04891CA82E22971E0064A111 /* LRUCache.swift */; }; 04891CAA2E22971E0064A111 /* LRUCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04891CA82E22971E0064A111 /* LRUCache.swift */; }; 04AD0B4E2E25B9580002A40A /* IdentityModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E2446380E7A44E49A35B664 /* IdentityModels.swift */; }; @@ -133,6 +135,7 @@ 04636BCE2E30BE5100FBCFA8 /* TestConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestConstants.swift; sourceTree = ""; }; 04636BCF2E30BE5100FBCFA8 /* TestHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHelpers.swift; sourceTree = ""; }; 04636BE12E30BEC600FBCFA8 /* IntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrationTests.swift; sourceTree = ""; }; + 04636BEC2E30CD4A00FBCFA8 /* NoiseHandshakeCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoiseHandshakeCoordinator.swift; sourceTree = ""; }; 04891CA82E22971E0064A111 /* LRUCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LRUCache.swift; sourceTree = ""; }; 04B6BA412E2035530090FE39 /* NoiseProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoiseProtocol.swift; sourceTree = ""; }; 04B6BA422E2035530090FE39 /* NoiseSecurityConsiderations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoiseSecurityConsiderations.swift; sourceTree = ""; }; @@ -226,6 +229,7 @@ 04B6BA442E2035530090FE39 /* Noise */ = { isa = PBXGroup; children = ( + 04636BEC2E30CD4A00FBCFA8 /* NoiseHandshakeCoordinator.swift */, 04B6BA412E2035530090FE39 /* NoiseProtocol.swift */, 04B6BA422E2035530090FE39 /* NoiseSecurityConsiderations.swift */, 04B6BA432E2035530090FE39 /* NoiseSession.swift */, @@ -563,6 +567,7 @@ 04AD0B4F2E25B9580002A40A /* SecureIdentityStateManager.swift in Sources */, 31D147471B9F4E2815352DDA /* LinkPreviewView.swift in Sources */, 04B6BA572E203D6C0090FE39 /* FingerprintView.swift in Sources */, + 04636BED2E30CD4A00FBCFA8 /* NoiseHandshakeCoordinator.swift in Sources */, C99763A4761567F587D21688 /* MessageRetryService.swift in Sources */, 749D8CF8A362B6CD0786782D /* NotificationService.swift in Sources */, 04636BBF2E2FCA8A00FBCFA8 /* SecureLogger.swift in Sources */, @@ -595,6 +600,7 @@ 1AF9F9036DEE42408D557A87 /* SecureIdentityStateManager.swift in Sources */, 7A5B1AB5642FEC168E917949 /* LinkPreviewView.swift in Sources */, 04B6BA552E203D6C0090FE39 /* FingerprintView.swift in Sources */, + 04636BEE2E30CD4A00FBCFA8 /* NoiseHandshakeCoordinator.swift in Sources */, CEAE115C9C3EB3C4ED82F128 /* MessageRetryService.swift in Sources */, 61C81ED5F679D5E973EE0C07 /* NotificationService.swift in Sources */, 04636BC02E2FCA8A00FBCFA8 /* SecureLogger.swift in Sources */, diff --git a/bitchat/Services/BluetoothMeshService.swift b/bitchat/Services/BluetoothMeshService.swift index 3b20d30e..15ca8b70 100644 --- a/bitchat/Services/BluetoothMeshService.swift +++ b/bitchat/Services/BluetoothMeshService.swift @@ -345,10 +345,24 @@ 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) + // Clear the old session instead of migrating it + // This ensures both peers do a fresh handshake after ID rotation + self.noiseService.removePeer(oldID) + + // Reset handshake state for both old and new peer IDs + self.handshakeCoordinator.resetHandshakeState(for: oldID) + self.handshakeCoordinator.resetHandshakeState(for: newPeerID) + + // Log the peer ID rotation + SecureLogger.log("Cleared session for peer ID rotation: \(oldID) -> \(newPeerID), will establish fresh handshake", + category: SecureLogger.handshake, level: .info) self.notifyPeerIDChange(oldPeerID: oldID, newPeerID: newPeerID, fingerprint: fingerprint) + + // Trigger handshake after a short delay to allow the peer to settle + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in + self?.initiateNoiseHandshake(with: newPeerID) + } } } }