Modularization: Extract SecureLogger into a separate module (#600)

* Extract SecureLogger into a separate module

* Add BitLogger package as a dependency for iOS & macOS targets
This commit is contained in:
Islam
2025-09-15 14:45:58 +02:00
committed by GitHub
parent 7c4bde59b9
commit 347ce5ece4
25 changed files with 118 additions and 47 deletions
+2
View File
@@ -15,6 +15,7 @@ let package = Package(
),
],
dependencies:[
.package(path: "localPackages/BitLogger"),
.package(url: "https://github.com/21-DOT-DEV/swift-secp256k1", exact: "0.21.1")
],
targets: [
@@ -22,6 +23,7 @@ let package = Package(
name: "bitchat",
dependencies: [
.product(name: "P256K", package: "swift-secp256k1"),
.product(name: "BitLogger", package: "BitLogger"),
.target(name: "TorC"),
.target(name: "tor-nolzma")
],
+22
View File
@@ -14,6 +14,8 @@
17901751FD8010AFC8E750F2 /* bitchatShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 61F92EBA29C47C0FCC482F1F /* bitchatShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
3EE336D150427F736F32B56C /* P256K in Frameworks */ = {isa = PBXBuildFile; productRef = B1D9136AA0083366353BFA2F /* P256K */; };
885BBED78092484A5B069461 /* P256K in Frameworks */ = {isa = PBXBuildFile; productRef = 4EB6BA1B8464F1EA38F4E286 /* P256K */; };
A6E3E5702E77036A0032EA8A /* BitLogger in Frameworks */ = {isa = PBXBuildFile; productRef = A6E3E56F2E77036A0032EA8A /* BitLogger */; };
A6E3E5722E7703760032EA8A /* BitLogger in Frameworks */ = {isa = PBXBuildFile; productRef = A6E3E5712E7703760032EA8A /* BitLogger */; };
E0A1B2C3D4E5F6012345678D /* relays/online_relays_gps.csv in Resources */ = {isa = PBXBuildFile; fileRef = E0A1B2C3D4E5F6012345678A /* relays/online_relays_gps.csv */; };
E0A1B2C3D4E5F6012345678E /* relays/online_relays_gps.csv in Resources */ = {isa = PBXBuildFile; fileRef = E0A1B2C3D4E5F6012345678A /* relays/online_relays_gps.csv */; };
/* End PBXBuildFile section */
@@ -133,6 +135,7 @@
31F6FDADA63050361C14F3A1 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
files = (
A6E3E5722E7703760032EA8A /* BitLogger in Frameworks */,
048A88812E76FD18000FBCDD /* libz.tbd in Frameworks */,
0481A3A02E744D6300FC845E /* tor-nolzma.xcframework in Frameworks */,
3EE336D150427F736F32B56C /* P256K in Frameworks */,
@@ -141,6 +144,7 @@
B5A5CC493FFB3D8966548140 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
files = (
A6E3E5702E77036A0032EA8A /* BitLogger in Frameworks */,
0481A35D2E6DA18600FC845E /* libz.tbd in Frameworks */,
0481A3A12E744D6300FC845E /* tor-nolzma.xcframework in Frameworks */,
885BBED78092484A5B069461 /* P256K in Frameworks */,
@@ -202,6 +206,7 @@
name = bitchat_macOS;
packageProductDependencies = (
B1D9136AA0083366353BFA2F /* P256K */,
A6E3E5712E7703760032EA8A /* BitLogger */,
);
productName = bitchat_macOS;
productReference = 8F3A7C058C2C8E1A06C8CF8B /* bitchat.app */;
@@ -278,6 +283,7 @@
name = bitchat_iOS;
packageProductDependencies = (
4EB6BA1B8464F1EA38F4E286 /* P256K */,
A6E3E56F2E77036A0032EA8A /* BitLogger */,
);
productName = bitchat_iOS;
productReference = 96D0D41CA19EE5A772AA8434 /* bitchat.app */;
@@ -303,6 +309,7 @@
minimizedProjectReferenceProxies = 1;
packageReferences = (
B8C407587481BBB190741C93 /* XCRemoteSwiftPackageReference "swift-secp256k1" */,
A6E3E56E2E77036A0032EA8A /* XCLocalSwiftPackageReference "localPackages/BitLogger" */,
);
preferredProjectObjectVersion = 90;
projectDirPath = "";
@@ -853,6 +860,13 @@
};
/* End XCConfigurationList section */
/* Begin XCLocalSwiftPackageReference section */
A6E3E56E2E77036A0032EA8A /* XCLocalSwiftPackageReference "localPackages/BitLogger" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = localPackages/BitLogger;
};
/* End XCLocalSwiftPackageReference section */
/* Begin XCRemoteSwiftPackageReference section */
B8C407587481BBB190741C93 /* XCRemoteSwiftPackageReference "swift-secp256k1" */ = {
isa = XCRemoteSwiftPackageReference;
@@ -870,6 +884,14 @@
package = B8C407587481BBB190741C93 /* XCRemoteSwiftPackageReference "swift-secp256k1" */;
productName = P256K;
};
A6E3E56F2E77036A0032EA8A /* BitLogger */ = {
isa = XCSwiftPackageProductDependency;
productName = BitLogger;
};
A6E3E5712E7703760032EA8A /* BitLogger */ = {
isa = XCSwiftPackageProductDependency;
productName = BitLogger;
};
B1D9136AA0083366353BFA2F /* P256K */ = {
isa = XCSwiftPackageProductDependency;
package = B8C407587481BBB190741C93 /* XCRemoteSwiftPackageReference "swift-secp256k1" */;
@@ -90,6 +90,7 @@
/// - Advanced conflict resolution
///
import BitLogger
import Foundation
import CryptoKit
@@ -6,6 +6,7 @@
// For more information, see <https://unlicense.org>
//
import BitLogger
import Foundation
/// Coordinates Noise handshakes to prevent race conditions and ensure reliable encryption establishment
+1
View File
@@ -77,6 +77,7 @@
/// - Noise Specification: http://www.noiseprotocol.org/noise.html
///
import BitLogger
import Foundation
import CryptoKit
@@ -6,6 +6,7 @@
// For more information, see <https://unlicense.org>
//
import BitLogger
import Foundation
import CryptoKit
+1
View File
@@ -6,6 +6,7 @@
// For more information, see <https://unlicense.org>
//
import BitLogger
import Foundation
import CryptoKit
+1
View File
@@ -1,3 +1,4 @@
import BitLogger
import Foundation
/// Directory of online Nostr relays with approximate GPS locations, used for geohash routing.
+1
View File
@@ -1,3 +1,4 @@
import BitLogger
import Foundation
import CryptoKit
import P256K
+1
View File
@@ -1,3 +1,4 @@
import BitLogger
import Foundation
import Network
import Combine
+1
View File
@@ -1,3 +1,4 @@
import BitLogger
import Foundation
import CoreBluetooth
import Combine
@@ -1,3 +1,4 @@
import BitLogger
import Foundation
import Combine
+1
View File
@@ -6,6 +6,7 @@
// For more information, see <https://unlicense.org>
//
import BitLogger
import Foundation
import Security
@@ -1,3 +1,4 @@
import BitLogger
import Foundation
import Combine
@@ -1,3 +1,4 @@
import BitLogger
import Foundation
/// Persistent location notes (Nostr kind 1) scoped to a street-level geohash (precision 7).
+1
View File
@@ -1,3 +1,4 @@
import BitLogger
import Foundation
/// Routes messages between BLE and Nostr transports
@@ -83,6 +83,7 @@
/// - Background queue for CPU-intensive operations
///
import BitLogger
import Foundation
import CryptoKit
+1
View File
@@ -1,3 +1,4 @@
import BitLogger
import Foundation
import Combine
@@ -6,6 +6,7 @@
// This is free and unencumbered software released into the public domain.
//
import BitLogger
import Foundation
import SwiftUI
+1
View File
@@ -1,3 +1,4 @@
import BitLogger
import Foundation
import Network
import Darwin
@@ -6,6 +6,7 @@
// This is free and unencumbered software released into the public domain.
//
import BitLogger
import Foundation
import Combine
import SwiftUI
+1
View File
@@ -77,6 +77,7 @@
/// ```
///
import BitLogger
import Foundation
import SwiftUI
import CryptoKit
+23
View File
@@ -0,0 +1,23 @@
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "BitLogger",
platforms: [
.iOS(.v16),
.macOS(.v13)
],
products: [
.library(
name: "BitLogger",
targets: ["BitLogger"]
)
],
targets: [
.target(
name: "BitLogger",
path: "Sources"
)
]
)
@@ -1,6 +1,6 @@
//
// OSLog+Categories.swift
// bitchat
// BitLogger
//
// This is free and unencumbered software released into the public domain.
// For more information, see <https://unlicense.org>
@@ -8,7 +8,7 @@
import os.log
extension OSLog {
public extension OSLog {
private static let subsystem = "chat.bitchat"
static let noise = OSLog(subsystem: subsystem, category: "noise")
@@ -1,6 +1,6 @@
//
// SecureLogger.swift
// bitchat
// BitLogger
//
// This is free and unencumbered software released into the public domain.
// For more information, see <https://unlicense.org>
@@ -11,7 +11,7 @@ import os.log
/// Centralized security-aware logging framework
/// Provides safe logging that filters sensitive data and security events
final class SecureLogger {
public final class SecureLogger {
// MARK: - Timestamp Formatter
@@ -85,8 +85,50 @@ final class SecureLogger {
private static func shouldLog(_ level: LogLevel) -> Bool {
return level.order >= minimumLevel.order
}
}
// MARK: - Public Logging Methods
public extension SecureLogger {
// MARK: - Security Event Types
static func debug(_ message: @autoclosure () -> String, category: OSLog = .noise,
file: String = #file, line: Int = #line, function: String = #function) {
log(message(), category: category, level: .debug, file: file, line: line, function: function)
}
static func info(_ message: @autoclosure () -> String, category: OSLog = .noise,
file: String = #file, line: Int = #line, function: String = #function) {
log(message(), category: category, level: .info, file: file, line: line, function: function)
}
static func warning(_ message: @autoclosure () -> String, category: OSLog = .noise,
file: String = #file, line: Int = #line, function: String = #function) {
log(message(), category: category, level: .warning, file: file, line: line, function: function)
}
static func error(_ message: @autoclosure () -> String, category: OSLog = .noise,
file: String = #file, line: Int = #line, function: String = #function) {
log(message(), category: category, 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) {
let location = formatLocation(file: file, line: line, function: function)
let sanitized = sanitize(context())
let errorDesc = sanitize(error.localizedDescription)
#if DEBUG
os_log("%{public}@ Error in %{public}@: %{public}@", log: category, type: .error, location, sanitized, errorDesc)
#else
os_log("%{private}@ Error in %{private}@: %{private}@", log: category, type: .error, location, sanitized, errorDesc)
#endif
}
}
// MARK: Security Event Logging
public extension SecureLogger {
enum SecurityEvent {
case handshakeStarted(peerID: String)
@@ -111,30 +153,6 @@ final class SecureLogger {
}
}
// MARK: - Public Logging Methods
static func debug(_ message: @autoclosure () -> String, category: OSLog = .noise,
file: String = #file, line: Int = #line, function: String = #function) {
log(message(), category: category, level: .debug, file: file, line: line, function: function)
}
static func info(_ message: @autoclosure () -> String, category: OSLog = .noise,
file: String = #file, line: Int = #line, function: String = #function) {
log(message(), category: category, level: .info, file: file, line: line, function: function)
}
static func warning(_ message: @autoclosure () -> String, category: OSLog = .noise,
file: String = #file, line: Int = #line, function: String = #function) {
log(message(), category: category, level: .warning, file: file, line: line, function: function)
}
static func error(_ message: @autoclosure () -> String, category: OSLog = .noise,
file: String = #file, line: Int = #line, function: String = #function) {
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)
}
@@ -150,25 +168,11 @@ final class SecureLogger {
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) {
let location = formatLocation(file: file, line: line, function: function)
let sanitized = sanitize(context())
let errorDesc = sanitize(error.localizedDescription)
#if DEBUG
os_log("%{public}@ Error in %{public}@: %{public}@", log: category, type: .error, location, sanitized, errorDesc)
#else
os_log("%{private}@ Error in %{private}@: %{private}@", log: category, type: .error, location, sanitized, errorDesc)
#endif
}
}
// MARK: - Convenience Extensions
extension SecureLogger {
public extension SecureLogger {
enum KeyOperation: String, CustomStringConvertible {
case load
@@ -177,7 +181,7 @@ extension SecureLogger {
case delete
case save
var description: String { rawValue }
public var description: String { rawValue }
}
/// Log key management operations
@@ -290,8 +294,8 @@ private extension SecureLogger {
/// Helper to migrate from print statements to SecureLogger
/// Usage: Replace print(...) with secureLog(...)
func secureLog(_ items: Any..., separator: String = " ", terminator: String = "\n",
file: String = #file, line: Int = #line, function: String = #function) {
public func secureLog(_ items: Any..., separator: String = " ", terminator: String = "\n",
file: String = #file, line: Int = #line, function: String = #function) {
#if DEBUG
let message = items.map { String(describing: $0) }.joined(separator: separator)
SecureLogger.debug(message, file: file, line: line, function: function)