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).
This commit is contained in:
jack
2025-07-23 10:35:13 +02:00
parent 0243397ba2
commit fb35d59dc9
2 changed files with 22 additions and 2 deletions
+6
View File
@@ -30,6 +30,8 @@
04636BE02E30BE5100FBCFA8 /* PublicChatE2ETests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04636BC52E30BE5100FBCFA8 /* PublicChatE2ETests.swift */; }; 04636BE02E30BE5100FBCFA8 /* PublicChatE2ETests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04636BC52E30BE5100FBCFA8 /* PublicChatE2ETests.swift */; };
04636BE82E30BEC600FBCFA8 /* IntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04636BE12E30BEC600FBCFA8 /* IntegrationTests.swift */; }; 04636BE82E30BEC600FBCFA8 /* IntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04636BE12E30BEC600FBCFA8 /* IntegrationTests.swift */; };
04636BEB2E30BEC600FBCFA8 /* 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 */; }; 04891CA92E22971E0064A111 /* LRUCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04891CA82E22971E0064A111 /* LRUCache.swift */; };
04891CAA2E22971E0064A111 /* 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 */; }; 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 = "<group>"; }; 04636BCE2E30BE5100FBCFA8 /* TestConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestConstants.swift; sourceTree = "<group>"; };
04636BCF2E30BE5100FBCFA8 /* TestHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHelpers.swift; sourceTree = "<group>"; }; 04636BCF2E30BE5100FBCFA8 /* TestHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHelpers.swift; sourceTree = "<group>"; };
04636BE12E30BEC600FBCFA8 /* IntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrationTests.swift; sourceTree = "<group>"; }; 04636BE12E30BEC600FBCFA8 /* IntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrationTests.swift; sourceTree = "<group>"; };
04636BEC2E30CD4A00FBCFA8 /* NoiseHandshakeCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoiseHandshakeCoordinator.swift; sourceTree = "<group>"; };
04891CA82E22971E0064A111 /* LRUCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LRUCache.swift; sourceTree = "<group>"; }; 04891CA82E22971E0064A111 /* LRUCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LRUCache.swift; sourceTree = "<group>"; };
04B6BA412E2035530090FE39 /* NoiseProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoiseProtocol.swift; sourceTree = "<group>"; }; 04B6BA412E2035530090FE39 /* NoiseProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoiseProtocol.swift; sourceTree = "<group>"; };
04B6BA422E2035530090FE39 /* NoiseSecurityConsiderations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoiseSecurityConsiderations.swift; sourceTree = "<group>"; }; 04B6BA422E2035530090FE39 /* NoiseSecurityConsiderations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoiseSecurityConsiderations.swift; sourceTree = "<group>"; };
@@ -226,6 +229,7 @@
04B6BA442E2035530090FE39 /* Noise */ = { 04B6BA442E2035530090FE39 /* Noise */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
04636BEC2E30CD4A00FBCFA8 /* NoiseHandshakeCoordinator.swift */,
04B6BA412E2035530090FE39 /* NoiseProtocol.swift */, 04B6BA412E2035530090FE39 /* NoiseProtocol.swift */,
04B6BA422E2035530090FE39 /* NoiseSecurityConsiderations.swift */, 04B6BA422E2035530090FE39 /* NoiseSecurityConsiderations.swift */,
04B6BA432E2035530090FE39 /* NoiseSession.swift */, 04B6BA432E2035530090FE39 /* NoiseSession.swift */,
@@ -563,6 +567,7 @@
04AD0B4F2E25B9580002A40A /* SecureIdentityStateManager.swift in Sources */, 04AD0B4F2E25B9580002A40A /* SecureIdentityStateManager.swift in Sources */,
31D147471B9F4E2815352DDA /* LinkPreviewView.swift in Sources */, 31D147471B9F4E2815352DDA /* LinkPreviewView.swift in Sources */,
04B6BA572E203D6C0090FE39 /* FingerprintView.swift in Sources */, 04B6BA572E203D6C0090FE39 /* FingerprintView.swift in Sources */,
04636BED2E30CD4A00FBCFA8 /* NoiseHandshakeCoordinator.swift in Sources */,
C99763A4761567F587D21688 /* MessageRetryService.swift in Sources */, C99763A4761567F587D21688 /* MessageRetryService.swift in Sources */,
749D8CF8A362B6CD0786782D /* NotificationService.swift in Sources */, 749D8CF8A362B6CD0786782D /* NotificationService.swift in Sources */,
04636BBF2E2FCA8A00FBCFA8 /* SecureLogger.swift in Sources */, 04636BBF2E2FCA8A00FBCFA8 /* SecureLogger.swift in Sources */,
@@ -595,6 +600,7 @@
1AF9F9036DEE42408D557A87 /* SecureIdentityStateManager.swift in Sources */, 1AF9F9036DEE42408D557A87 /* SecureIdentityStateManager.swift in Sources */,
7A5B1AB5642FEC168E917949 /* LinkPreviewView.swift in Sources */, 7A5B1AB5642FEC168E917949 /* LinkPreviewView.swift in Sources */,
04B6BA552E203D6C0090FE39 /* FingerprintView.swift in Sources */, 04B6BA552E203D6C0090FE39 /* FingerprintView.swift in Sources */,
04636BEE2E30CD4A00FBCFA8 /* NoiseHandshakeCoordinator.swift in Sources */,
CEAE115C9C3EB3C4ED82F128 /* MessageRetryService.swift in Sources */, CEAE115C9C3EB3C4ED82F128 /* MessageRetryService.swift in Sources */,
61C81ED5F679D5E973EE0C07 /* NotificationService.swift in Sources */, 61C81ED5F679D5E973EE0C07 /* NotificationService.swift in Sources */,
04636BC02E2FCA8A00FBCFA8 /* SecureLogger.swift in Sources */, 04636BC02E2FCA8A00FBCFA8 /* SecureLogger.swift in Sources */,
+16 -2
View File
@@ -345,10 +345,24 @@ class BluetoothMeshService: NSObject {
// Notify about the change if it's a rotation // Notify about the change if it's a rotation
if let oldID = oldPeerID { if let oldID = oldPeerID {
// Migrate Noise session to new peer ID // Clear the old session instead of migrating it
self.noiseService.migratePeerSession(from: oldID, to: newPeerID, fingerprint: fingerprint) // 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) 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)
}
} }
} }
} }