From e5a415d885315fcd3df8bde2f5c6e0a2ef132b6b Mon Sep 17 00:00:00 2001 From: islam <2553451+qalandarov@users.noreply.github.com> Date: Thu, 11 Sep 2025 11:54:30 +0100 Subject: [PATCH] =?UTF-8?q?Overloading=20`.debug/.error`=20for=20=E2=80=98?= =?UTF-8?q?.logSecurityEvent=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Search/Replace Strategies: 1. Search regex: `SecureLogger\.logSecurityEvent\(\s*(.*?),\s*level:\s*\.(\w+)\s*\)` Replace regex: `SecureLogger.$2($1)` Sample input: `SecureLogger.logSecurityEvent(.authenticationFailed(peerID: peerID), level: .warning)` Sample output: `SecureLogger.warning(.authenticationFailed(peerID: peerID))` --- 2. Search regex: `SecureLogger\.logSecurityEvent\(\s*(.*?)\s*\)` Replace regex: `SecureLogger.info($1)` (`info` is the default level) Sample input: `SecureLogger.logSecurityEvent(.handshakeStarted(peerID: peerID))` Sample output: `SecureLogger.info(.handshakeStarted(peerID: peerID))` --- bitchat/Noise/NoiseProtocol.swift | 2 +- bitchat/Noise/NoiseSession.swift | 12 ++--- bitchat/Services/NoiseEncryptionService.swift | 16 +++---- bitchat/Utils/SecureLogger.swift | 48 +++++++++++++------ 4 files changed, 48 insertions(+), 30 deletions(-) diff --git a/bitchat/Noise/NoiseProtocol.swift b/bitchat/Noise/NoiseProtocol.swift index ae3da305..8b0adbfe 100644 --- a/bitchat/Noise/NoiseProtocol.swift +++ b/bitchat/Noise/NoiseProtocol.swift @@ -678,7 +678,7 @@ final class NoiseHandshakeState { let decrypted = try symmetricState.decryptAndHash(staticData) remoteStaticPublic = try NoiseHandshakeState.validatePublicKey(decrypted) } catch { - SecureLogger.logSecurityEvent(.authenticationFailed(peerID: "Unknown - handshake"), level: .error) + SecureLogger.error(.authenticationFailed(peerID: "Unknown - handshake")) throw NoiseError.authenticationFailure } diff --git a/bitchat/Noise/NoiseSession.swift b/bitchat/Noise/NoiseSession.swift index ec2b6ec0..c6fbb727 100644 --- a/bitchat/Noise/NoiseSession.swift +++ b/bitchat/Noise/NoiseSession.swift @@ -131,7 +131,7 @@ class NoiseSession { handshakeState = nil // Clear handshake state SecureLogger.debug("NoiseSession[\(peerID)]: Handshake complete (no response needed), transitioning to established", category: .noise) - SecureLogger.logSecurityEvent(.handshakeCompleted(peerID: peerID)) + SecureLogger.info(.handshakeCompleted(peerID: peerID)) return nil } else { @@ -157,7 +157,7 @@ class NoiseSession { handshakeState = nil // Clear handshake state SecureLogger.debug("NoiseSession[\(peerID)]: Handshake complete after writing response, transitioning to established", category: .noise) - SecureLogger.logSecurityEvent(.handshakeCompleted(peerID: peerID)) + SecureLogger.info(.handshakeCompleted(peerID: peerID)) } return response @@ -242,7 +242,7 @@ class NoiseSession { handshakeHash = nil if wasEstablished { - SecureLogger.logSecurityEvent(.sessionExpired(peerID: peerID)) + SecureLogger.info(.sessionExpired(peerID: peerID)) } } } @@ -287,7 +287,7 @@ final class NoiseSessionManager { managerQueue.sync(flags: .barrier) { if let session = sessions[peerID] { if session.isEstablished() { - SecureLogger.logSecurityEvent(.sessionExpired(peerID: peerID)) + SecureLogger.info(.sessionExpired(peerID: peerID)) } // Clear sensitive data before removing session.reset() @@ -331,7 +331,7 @@ final class NoiseSessionManager { } catch { // Clean up failed session _ = sessions.removeValue(forKey: peerID) - SecureLogger.logSecurityEvent(.handshakeFailed(peerID: peerID, error: error.localizedDescription), level: .error) + SecureLogger.error(.handshakeFailed(peerID: peerID, error: error.localizedDescription)) throw error } } @@ -403,7 +403,7 @@ final class NoiseSessionManager { self?.onSessionFailed?(peerID, error) } - SecureLogger.logSecurityEvent(.handshakeFailed(peerID: peerID, error: error.localizedDescription), level: .error) + SecureLogger.error(.handshakeFailed(peerID: peerID, error: error.localizedDescription)) throw error } } diff --git a/bitchat/Services/NoiseEncryptionService.swift b/bitchat/Services/NoiseEncryptionService.swift index 12aa1b1a..9c6be08e 100644 --- a/bitchat/Services/NoiseEncryptionService.swift +++ b/bitchat/Services/NoiseEncryptionService.swift @@ -392,17 +392,17 @@ final class NoiseEncryptionService { // Validate peer ID guard NoiseSecurityValidator.validatePeerID(peerID) else { - SecureLogger.logSecurityEvent(.authenticationFailed(peerID: peerID), level: .warning) + SecureLogger.warning(.authenticationFailed(peerID: peerID)) throw NoiseSecurityError.invalidPeerID } // Check rate limit guard rateLimiter.allowHandshake(from: peerID) else { - SecureLogger.logSecurityEvent(.authenticationFailed(peerID: "Rate limited: \(peerID)"), level: .warning) + SecureLogger.warning(.authenticationFailed(peerID: "Rate limited: \(peerID)")) throw NoiseSecurityError.rateLimitExceeded } - SecureLogger.logSecurityEvent(.handshakeStarted(peerID: peerID)) + SecureLogger.info(.handshakeStarted(peerID: peerID)) // Return raw handshake data without wrapper // The Noise protocol handles its own message format @@ -415,19 +415,19 @@ final class NoiseEncryptionService { // Validate peer ID guard NoiseSecurityValidator.validatePeerID(peerID) else { - SecureLogger.logSecurityEvent(.authenticationFailed(peerID: peerID), level: .warning) + SecureLogger.warning(.authenticationFailed(peerID: peerID)) throw NoiseSecurityError.invalidPeerID } // Validate message size guard NoiseSecurityValidator.validateHandshakeMessageSize(message) else { - SecureLogger.logSecurityEvent(.handshakeFailed(peerID: peerID, error: "Message too large"), level: .warning) + SecureLogger.warning(.handshakeFailed(peerID: peerID, error: "Message too large")) throw NoiseSecurityError.messageTooLarge } // Check rate limit guard rateLimiter.allowHandshake(from: peerID) else { - SecureLogger.logSecurityEvent(.authenticationFailed(peerID: "Rate limited: \(peerID)"), level: .warning) + SecureLogger.warning(.authenticationFailed(peerID: "Rate limited: \(peerID)")) throw NoiseSecurityError.rateLimitExceeded } @@ -521,7 +521,7 @@ final class NoiseEncryptionService { peerFingerprints.removeValue(forKey: peerID) } - SecureLogger.logSecurityEvent(.sessionExpired(peerID: peerID)) + SecureLogger.info(.sessionExpired(peerID: peerID)) } // MARK: - Private Helpers @@ -537,7 +537,7 @@ final class NoiseEncryptionService { } // Log security event - SecureLogger.logSecurityEvent(.handshakeCompleted(peerID: peerID)) + SecureLogger.info(.handshakeCompleted(peerID: peerID)) // Notify all handlers about authentication serviceQueue.async { [weak self] in diff --git a/bitchat/Utils/SecureLogger.swift b/bitchat/Utils/SecureLogger.swift index 41867a8a..44349d6f 100644 --- a/bitchat/Utils/SecureLogger.swift +++ b/bitchat/Utils/SecureLogger.swift @@ -133,6 +133,24 @@ final class SecureLogger { log(message(), category: category, level: .error, file: file, line: line, function: function) } + // MARK: Security Event Logging + + static func debug(_ event: SecurityEvent, file: String = #file, line: Int = #line, function: String = #function) { + logSecurityEvent(event, level: .debug, file: file, line: line, function: function) + } + + static func info(_ event: SecurityEvent, file: String = #file, line: Int = #line, function: String = #function) { + logSecurityEvent(event, level: .info, file: file, line: line, function: function) + } + + static func warning(_ event: SecurityEvent, file: String = #file, line: Int = #line, function: String = #function) { + logSecurityEvent(event, level: .warning, file: file, line: line, function: function) + } + + static func error(_ event: SecurityEvent, file: String = #file, line: Int = #line, function: String = #function) { + logSecurityEvent(event, level: .error, file: file, line: line, function: function) + } + /// Log errors with context static func error(_ error: Error, context: @autoclosure () -> String, category: OSLog = .noise, file: String = #file, line: Int = #line, function: String = #function) { @@ -147,21 +165,6 @@ final class SecureLogger { #endif } - /// Log a security event - static func logSecurityEvent(_ event: SecurityEvent, level: LogLevel = .info, - file: String = #file, line: Int = #line, function: String = #function) { - guard shouldLog(level) else { return } - let location = formatLocation(file: file, line: line, function: function) - let message = "\(location) \(event.message)" - - #if DEBUG - os_log("%{public}@", log: .security, type: level.osLogType, message) - #else - // In release, use private logging to prevent sensitive data exposure - os_log("%{private}@", log: .security, type: level.osLogType, message) - #endif - } - // MARK: - Private Helpers /// Log general messages with automatic sensitive data filtering @@ -181,6 +184,21 @@ final class SecureLogger { #endif } + /// Log a security event + private static func logSecurityEvent(_ event: SecurityEvent, level: LogLevel = .info, + file: String, line: Int, function: String) { + guard shouldLog(level) else { return } + let location = formatLocation(file: file, line: line, function: function) + let message = "\(location) \(event.message)" + + #if DEBUG + os_log("%{public}@", log: .security, type: level.osLogType, message) + #else + // In release, use private logging to prevent sensitive data exposure + os_log("%{private}@", log: .security, type: level.osLogType, message) + #endif + } + /// Format location information for logging private static func formatLocation(file: String, line: Int, function: String) -> String { let fileName = (file as NSString).lastPathComponent