diff --git a/bitchat/Identity/IdentityModels.swift b/bitchat/Identity/IdentityModels.swift index 8b20aec6..bb753977 100644 --- a/bitchat/Identity/IdentityModels.swift +++ b/bitchat/Identity/IdentityModels.swift @@ -87,7 +87,7 @@ import Foundation /// Represents the ephemeral layer of identity - short-lived peer IDs that provide network privacy. /// These IDs rotate periodically to prevent tracking while maintaining cryptographic relationships. struct EphemeralIdentity { - let peerID: String // 8 random bytes + let peer: Peer // 8 random bytes let sessionStart: Date var handshakeState: HandshakeState } diff --git a/bitchat/Identity/SecureIdentityStateManager.swift b/bitchat/Identity/SecureIdentityStateManager.swift index 339605b7..7342dd1f 100644 --- a/bitchat/Identity/SecureIdentityStateManager.swift +++ b/bitchat/Identity/SecureIdentityStateManager.swift @@ -121,12 +121,12 @@ protocol SecureIdentityStateManagerProtocol { func getBlockedNostrPubkeys() -> Set // MARK: Ephemeral Session Management - func registerEphemeralSession(peerID: String, handshakeState: HandshakeState) - func updateHandshakeState(peerID: String, state: HandshakeState) + func registerEphemeralSession(peer: Peer, handshakeState: HandshakeState) + func updateHandshakeState(peer: Peer, state: HandshakeState) // MARK: Cleanup func clearAllIdentityData() - func removeEphemeralSession(peerID: String) + func removeEphemeralSession(peer: Peer) // MARK: Verification func setVerified(fingerprint: String, verified: Bool) @@ -143,7 +143,7 @@ final class SecureIdentityStateManager: SecureIdentityStateManagerProtocol { private let encryptionKeyName = "identityCacheEncryptionKey" // In-memory state - private var ephemeralSessions: [String: EphemeralIdentity] = [:] + private var ephemeralSessions: [Peer: EphemeralIdentity] = [:] private var cryptographicIdentities: [String: CryptographicIdentity] = [:] private var cache: IdentityCache = IdentityCache() @@ -455,19 +455,19 @@ final class SecureIdentityStateManager: SecureIdentityStateManagerProtocol { // MARK: - Ephemeral Session Management - func registerEphemeralSession(peerID: String, handshakeState: HandshakeState = .none) { + func registerEphemeralSession(peer: Peer, handshakeState: HandshakeState = .none) { queue.async(flags: .barrier) { - self.ephemeralSessions[peerID] = EphemeralIdentity( - peerID: peerID, + self.ephemeralSessions[peer] = EphemeralIdentity( + peer: peer, sessionStart: Date(), handshakeState: handshakeState ) } } - func updateHandshakeState(peerID: String, state: HandshakeState) { + func updateHandshakeState(peer: Peer, state: HandshakeState) { queue.async(flags: .barrier) { - self.ephemeralSessions[peerID]?.handshakeState = state + self.ephemeralSessions[peer]?.handshakeState = state // If handshake completed, update last interaction if case .completed(let fingerprint) = state { @@ -493,9 +493,9 @@ final class SecureIdentityStateManager: SecureIdentityStateManagerProtocol { } } - func removeEphemeralSession(peerID: String) { + func removeEphemeralSession(peer: Peer) { queue.async(flags: .barrier) { - self.ephemeralSessions.removeValue(forKey: peerID) + self.ephemeralSessions.removeValue(forKey: peer) } } diff --git a/bitchat/ViewModels/ChatViewModel.swift b/bitchat/ViewModels/ChatViewModel.swift index 26342889..48d91f87 100644 --- a/bitchat/ViewModels/ChatViewModel.swift +++ b/bitchat/ViewModels/ChatViewModel.swift @@ -1298,7 +1298,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate { } // Update identity state manager with handshake completion - identityManager.updateHandshakeState(peerID: peerID, state: .completed(fingerprint: fingerprintStr)) + identityManager.updateHandshakeState(peer: Peer(str: peerID), state: .completed(fingerprint: fingerprintStr)) // Update encryption status now that we have the fingerprint updateEncryptionStatus(for: peerID) @@ -4608,7 +4608,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate { isConnected = true // Register ephemeral session with identity manager - identityManager.registerEphemeralSession(peerID: peerID, handshakeState: .none) + identityManager.registerEphemeralSession(peer: Peer(str: peerID), handshakeState: .none) // Intentionally do not resend favorites on reconnect. // We only send our npub when a favorite is toggled on, or if our npub changes. @@ -4633,7 +4633,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate { SecureLogger.debug("👋 Peer disconnected: \(peerID)", category: .session) // Remove ephemeral session from identity manager - identityManager.removeEphemeralSession(peerID: peerID) + identityManager.removeEphemeralSession(peer: Peer(str: peerID)) // If the open PM is tied to this short peer ID, switch UI context to the full Noise key (offline favorite) var derivedStableKeyHex: String? = shortIDToNoiseKey[peerID] @@ -4740,7 +4740,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate { // Register ephemeral sessions for all connected peers for peerID in peers { - self.identityManager.registerEphemeralSession(peerID: peerID, handshakeState: .none) + self.identityManager.registerEphemeralSession(peer: Peer(str: peerID), handshakeState: .none) } // Schedule UI refresh to ensure offline favorites are shown