Burn down SwiftLint advisory violations from 109 to 4 (#1362)

Mechanical style fixes across the enabled rule set, mostly via
swiftlint --fix (trailing_comma, comma, colon, trailing_newline,
comment_spacing, unused_closure_parameter, unneeded_break_in_switch,
opening_brace) plus hand fixes:

- non_optional_string_data_conversion (45): .data(using: .utf8)! and
  ?? Data() fallbacks replaced with the non-optional Data(_.utf8),
  including two production sites (NIP-44 HKDF info constant and the
  announce canonicalization context/nickname bytes — byte-identical
  output, only the impossible-nil handling is gone).
- switch_case_alignment: LocationChannel had a misindented closing
  brace; also repaired an --fix artifact in BLEService's .none case.
- redundant_string_enum_value: TrustLevel raw values equal to the case
  names (encoded form unchanged).
- unused_optional_binding: let _ = binds replaced with != nil / is Bool.
- static_over_final_class: PreviewView.layerClass.
- Resolved the BinaryProtocolTests TODO by documenting that 8-byte
  recipient ID truncation is the fixed wire-field size, not a bug.

The 4 remaining violations are all todo markers for a shared
test-helpers module (tracked in #1088) and one Reuse note.

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jack
2026-07-05 14:09:13 +02:00
committed by GitHub
co-authored by jack Claude Fable 5
parent 0f26a27980
commit b31a63ce37
33 changed files with 103 additions and 107 deletions
+2 -2
View File
@@ -13,9 +13,9 @@ let package = Package(
.executable(
name: "bitchat",
targets: ["bitchat"]
),
)
],
dependencies:[
dependencies: [
.package(path: "localPackages/Arti"),
.package(path: "localPackages/BitFoundation"),
.package(path: "localPackages/BitLogger"),
+1 -1
View File
@@ -71,7 +71,7 @@ struct BitchatApp: App {
final class AppDelegate: NSObject, UIApplicationDelegate {
weak var runtime: AppRuntime?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
true
}
+4 -4
View File
@@ -127,10 +127,10 @@ struct SocialIdentity: Codable {
}
enum TrustLevel: String, Codable {
case unknown = "unknown"
case casual = "casual"
case trusted = "trusted"
case verified = "verified"
case unknown
case casual
case trusted
case verified
}
// MARK: - Identity Cache
+1 -1
View File
@@ -648,7 +648,7 @@ private extension NostrProtocol {
let derivedKey = HKDF<CryptoKit.SHA256>.deriveKey(
inputKeyMaterial: SymmetricKey(data: sharedSecretData),
salt: Data(),
info: "nip44-v2".data(using: .utf8)!,
info: Data("nip44-v2".utf8),
outputByteCount: 32
)
return derivedKey.withUnsafeBytes { Data($0) }
@@ -132,4 +132,3 @@ private extension Data {
replaceSubrange(offset..<(offset+4), with: bytes)
}
}
+2 -3
View File
@@ -1305,7 +1305,7 @@ extension BLEService: GossipSyncManager.Delegate {
extension BLEService: CBCentralManagerDelegate {
#if os(iOS)
func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) {
func centralManager(_ central: CBCentralManager, willRestoreState dict: [String: Any]) {
let restoredPeripherals = (dict[CBCentralManagerRestoredStatePeripheralsKey] as? [CBPeripheral]) ?? []
let restoredServices = (dict[CBCentralManagerRestoredStateScanServicesKey] as? [CBUUID]) ?? []
let restoredOptions = (dict[CBCentralManagerRestoredStateScanOptionsKey] as? [String: Any]) ?? [:]
@@ -1987,7 +1987,7 @@ extension BLEService: CBPeripheralManagerDelegate {
}
#if os(iOS)
func peripheralManager(_ peripheral: CBPeripheralManager, willRestoreState dict: [String : Any]) {
func peripheralManager(_ peripheral: CBPeripheralManager, willRestoreState dict: [String: Any]) {
let restoredServices = (dict[CBPeripheralManagerRestoredStateServicesKey] as? [CBMutableService]) ?? []
let restoredAdvertisement = (dict[CBPeripheralManagerRestoredStateAdvertisementDataKey] as? [String: Any]) ?? [:]
@@ -2959,7 +2959,6 @@ extension BLEService {
case .none:
SecureLogger.warning("⚠️ Unknown message type: \(packet.type)", category: .session)
break
}
if forwardAlongRouteIfNeeded(packet) {
+1 -1
View File
@@ -51,7 +51,7 @@ final class MessageRouter {
}
// Handle key updates
if let newKey = note.userInfo?["peerPublicKey"] as? Data,
let _ = note.userInfo?["isKeyUpdate"] as? Bool {
note.userInfo?["isKeyUpdate"] is Bool {
let peerID = PeerID(publicKey: newKey)
Task { @MainActor in
self.flushOutbox(for: peerID)
@@ -428,7 +428,7 @@ final class NoiseEncryptionService {
private func canonicalAnnounceBytes(peerID: Data, noiseKey: Data, ed25519Key: Data, nickname: String, timestampMs: UInt64) -> Data {
var out = Data()
// context
let context = "bitchat-announce-v1".data(using: .utf8) ?? Data()
let context = Data("bitchat-announce-v1".utf8)
out.append(UInt8(min(context.count, 255)))
out.append(context.prefix(255))
// peerID (expect 8 bytes; pad/truncate to 8 for canonicalization)
@@ -444,7 +444,7 @@ final class NoiseEncryptionService {
out.append(ed32)
if ed32.count < 32 { out.append(Data(repeating: 0, count: 32 - ed32.count)) }
// nickname length + bytes
let nickData = nickname.data(using: .utf8) ?? Data()
let nickData = Data(nickname.utf8)
out.append(UInt8(min(nickData.count, 255)))
out.append(nickData.prefix(255))
// timestamp
+1 -1
View File
@@ -137,7 +137,7 @@ final class NostrTransport: Transport, @unchecked Sendable {
}
func peerNickname(peerID: PeerID) -> String? { nil }
func getPeerNicknames() -> [PeerID : String] { [:] }
func getPeerNicknames() -> [PeerID: String] { [:] }
func getFingerprint(for peerID: PeerID) -> String? { nil }
func getNoiseSessionState(for peerID: PeerID) -> LazyHandshakeState { .none }
+1 -1
View File
@@ -111,7 +111,7 @@ final class NotificationService {
func requestAuthorization() {
guard !isRunningTests else { return }
authorizer.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
authorizer.requestAuthorization(options: [.alert, .sound, .badge]) { granted, _ in
if granted {
// Permission granted
} else {
@@ -27,4 +27,3 @@ struct PeerDisplayNameResolver {
return result
}
}
@@ -71,7 +71,7 @@ final class ChatNostrCoordinator {
key: Data?
) {
guard let context else { return }
if let _ = key {
if key != nil {
if let identity = context.currentNostrIdentity() {
context.sendGeohashDeliveryAck(for: message.id, toRecipientHex: senderPubkey, from: identity)
}
@@ -84,7 +84,7 @@ final class ChatNostrCoordinator {
}
if !wasReadBefore && context.selectedPrivateChatPeer == message.senderPeerID {
if let _ = key {
if key != nil {
if let identity = context.currentNostrIdentity() {
context.sendGeohashReadReceipt(message.id, toRecipientHex: senderPubkey, from: identity)
}
+2 -2
View File
@@ -426,6 +426,6 @@ private extension ChannelID {
}
}
//#Preview {
// #Preview {
// MessageListView()
//}
// }
+1 -1
View File
@@ -265,7 +265,7 @@ struct CameraScannerView: UIViewRepresentable {
}
final class PreviewView: UIView {
override class var layerClass: AnyClass { AVCaptureVideoPreviewLayer.self }
override static var layerClass: AnyClass { AVCaptureVideoPreviewLayer.self }
var videoPreviewLayer: AVCaptureVideoPreviewLayer { layer as! AVCaptureVideoPreviewLayer }
override init(frame: CGRect) {
super.init(frame: frame)
@@ -84,7 +84,7 @@ final class ShareViewController: UIViewController {
self.loadFirstPlainText(from: providers) { text in
if let t = text, !t.isEmpty {
// Treat as URL if parseable http(s), else plain text
if let u = URL(string: t), ["http","https"].contains(u.scheme?.lowercased() ?? "") {
if let u = URL(string: t), ["http", "https"].contains(u.scheme?.lowercased() ?? "") {
self.saveAndFinish(url: u, title: item.attributedTitle?.string)
} else {
self.saveAndFinish(text: t)
@@ -82,7 +82,7 @@ struct ChatComposerCoordinatorContextTests {
context.meshNicknamesByPeerID = [
PeerID(str: "1111111111111111"): "alice",
PeerID(str: "2222222222222222"): "bob",
PeerID(str: "3333333333333333"): "me",
PeerID(str: "3333333333333333"): "me"
]
// Matching query: suggestions and range are published, index resets.
@@ -113,7 +113,7 @@ struct ChatComposerCoordinatorContextTests {
"aaaabbbbccccdddd": "carol",
// Own token (nickname#last-4-of-pubkey) must be removed; the dummy
// identity's public key hex ends in "2222".
"ffffeeeeddddcccc2222": "me",
"ffffeeeeddddcccc2222": "me"
]
coordinator.updateAutocomplete(for: "@ca", cursorPosition: 3)
@@ -214,10 +214,10 @@ struct ChatLifecycleCoordinatorContextTests {
// Same message under both keys: the read copy must win over sent.
context.privateChats[peerID] = [
makePrivateMessage(id: "m1", timestamp: t1, deliveryStatus: .sent),
makePrivateMessage(id: "m2", timestamp: t2),
makePrivateMessage(id: "m2", timestamp: t2)
]
context.privateChats[stablePeerID] = [
makePrivateMessage(id: "m1", timestamp: t1, deliveryStatus: .read(by: "alice", at: t2)),
makePrivateMessage(id: "m1", timestamp: t1, deliveryStatus: .read(by: "alice", at: t2))
]
let merged = coordinator.getPrivateChatMessages(for: peerID)
@@ -245,7 +245,7 @@ struct ChatLifecycleCoordinatorContextTests {
makePrivateMessage(id: "m1", senderPeerID: convKey),
makePrivateMessage(id: "already-acked", senderPeerID: convKey),
makePrivateMessage(id: "relay", senderPeerID: convKey, isRelay: true),
makePrivateMessage(id: "mine", sender: "me", senderPeerID: context.myPeerID),
makePrivateMessage(id: "mine", sender: "me", senderPeerID: context.myPeerID)
]
coordinator.markPrivateMessagesAsRead(from: convKey)
@@ -339,7 +339,7 @@ struct ChatLifecycleCoordinatorContextTests {
)
context.privateChats[peerID] = [
makePrivateMessage(id: "in-1", senderPeerID: peerID),
makePrivateMessage(id: "in-relay", senderPeerID: peerID, isRelay: true),
makePrivateMessage(id: "in-relay", senderPeerID: peerID, isRelay: true)
]
coordinator.markPrivateMessagesAsRead(from: peerID)
@@ -154,18 +154,18 @@ struct ChatPeerListCoordinatorContextTests {
peerID: currentPeer,
noisePublicKey: Data(repeating: 0x01, count: 32),
nickname: "alice"
),
)
]
context.unreadPrivateMessages = [
currentPeer,
staleShortPeer,
geoDMWithMessages,
geoDMWithoutMessages,
noiseKeyWithMessages,
noiseKeyWithMessages
]
context.privateChats = [
geoDMWithMessages: [makeMessage(id: "geo-1")],
noiseKeyWithMessages: [makeMessage(id: "noise-1")],
noiseKeyWithMessages: [makeMessage(id: "noise-1")]
]
coordinator.didUpdatePeerList([currentPeer])
@@ -352,7 +352,7 @@ struct ChatPrivateConversationCoordinatorContextTests {
context.displayNamesByPubkey[senderPubkey] = "alice#1234"
context.privateChats[convKey] = [
makeIncomingMessage(id: "mine-1", sender: "me"),
makeIncomingMessage(id: "mine-2", sender: "me"),
makeIncomingMessage(id: "mine-2", sender: "me")
]
coordinator.handleDelivered(
@@ -259,7 +259,7 @@ struct ChatTransportEventCoordinatorContextTests {
context.privateChats[peerID] = [
makeMessage(id: "theirs-1", isPrivate: true, senderPeerID: peerID),
makeMessage(id: "mine-1", sender: "me", isPrivate: true, senderPeerID: context.myPeerID),
makeMessage(id: "theirs-2", isPrivate: true, senderPeerID: peerID),
makeMessage(id: "theirs-2", isPrivate: true, senderPeerID: peerID)
]
coordinator.didDisconnectFromPeer(peerID)
await drainMainActorTasks()
@@ -282,7 +282,7 @@ struct ChatTransportEventCoordinatorContextTests {
context.unreadPrivateMessages = [peerID]
context.privateChats[peerID] = [
makeMessage(id: "m1", isPrivate: true, senderPeerID: peerID),
makeMessage(id: "mine", sender: "me", isPrivate: true, senderPeerID: context.myPeerID),
makeMessage(id: "mine", sender: "me", isPrivate: true, senderPeerID: context.myPeerID)
]
coordinator.didDisconnectFromPeer(peerID)
@@ -174,7 +174,7 @@ struct IntegrationTests {
}
// Encrypted path: use NoiseSessionManager explicitly
let plaintext = "Encrypted message".data(using: .utf8)!
let plaintext = Data("Encrypted message".utf8)
let ciphertext = try helper.noiseManagers["Alice"]!.encrypt(plaintext, for: helper.nodes["Bob"]!.peerID)
helper.nodes["Bob"]!.packetDeliveryHandler = { packet in
@@ -206,7 +206,7 @@ struct IntegrationTests {
try await confirmation("Messages delivered despite churn", expectedCount: totalMessages) { completion in
// David tracks received messages
helper.nodes["David"]!.messageDeliveryHandler = { message in
helper.nodes["David"]!.messageDeliveryHandler = { _ in
completion()
}
@@ -288,7 +288,7 @@ struct IntegrationTests {
}
do {
let plaintext = "After restart success".data(using: .utf8)!
let plaintext = Data("After restart success".utf8)
let ciphertext = try helper.noiseManagers["Bob"]!.encrypt(plaintext, for: helper.nodes["Alice"]!.peerID)
let packet = TestHelpers.createTestPacket(type: MessageType.noiseEncrypted.rawValue, payload: ciphertext)
helper.nodes["Alice"]!.packetDeliveryHandler = { pkt in
@@ -121,4 +121,3 @@ final class TestNetworkHelper {
_ = try manager2.handleIncomingHandshake(from: peer1ID, message: msg3)
}
}
+1 -1
View File
@@ -172,7 +172,7 @@ struct NoiseCoverageTests {
Data(),
Data(repeating: 0x00, count: 32),
Data([0x01] + Array(repeating: 0x00, count: 31)),
Data(repeating: 0xFF, count: 32),
Data(repeating: 0xFF, count: 32)
]
for invalidKey in invalidKeys {
+27 -28
View File
@@ -151,7 +151,7 @@ struct NoiseProtocolTests {
@Test func basicEncryptionDecryption() throws {
try performHandshake(initiator: aliceSession, responder: bobSession)
let plaintext = "Hello, Bob!".data(using: .utf8)!
let plaintext = Data("Hello, Bob!".utf8)
// Alice encrypts
let ciphertext = try aliceSession.encrypt(plaintext)
@@ -167,13 +167,13 @@ struct NoiseProtocolTests {
try performHandshake(initiator: aliceSession, responder: bobSession)
// Alice -> Bob
let aliceMessage = "Hello from Alice".data(using: .utf8)!
let aliceMessage = Data("Hello from Alice".utf8)
let aliceCiphertext = try aliceSession.encrypt(aliceMessage)
let bobReceived = try bobSession.decrypt(aliceCiphertext)
#expect(bobReceived == aliceMessage)
// Bob -> Alice
let bobMessage = "Hello from Bob".data(using: .utf8)!
let bobMessage = Data("Hello from Bob".utf8)
let bobCiphertext = try bobSession.encrypt(bobMessage)
let aliceReceived = try aliceSession.decrypt(bobCiphertext)
#expect(aliceReceived == bobMessage)
@@ -193,7 +193,7 @@ struct NoiseProtocolTests {
}
@Test func encryptionBeforeHandshake() {
let plaintext = "test".data(using: .utf8)!
let plaintext = Data("test".utf8)
#expect(throws: NoiseSessionError.notEstablished) {
try aliceSession.encrypt(plaintext)
@@ -270,7 +270,7 @@ struct NoiseProtocolTests {
try establishManagerSessions(aliceManager: aliceManager, bobManager: bobManager)
// Encrypt with manager
let plaintext = "Test message".data(using: .utf8)!
let plaintext = Data("Test message".utf8)
let ciphertext = try aliceManager.encrypt(plaintext, for: alicePeerID)
// Decrypt with manager
@@ -283,7 +283,7 @@ struct NoiseProtocolTests {
@Test func tamperedCiphertextDetection() throws {
try performHandshake(initiator: aliceSession, responder: bobSession)
let plaintext = "Secret message".data(using: .utf8)!
let plaintext = Data("Secret message".utf8)
var ciphertext = try aliceSession.encrypt(plaintext)
// Tamper with ciphertext
@@ -304,7 +304,7 @@ struct NoiseProtocolTests {
@Test func replayPrevention() throws {
try performHandshake(initiator: aliceSession, responder: bobSession)
let plaintext = "Test message".data(using: .utf8)!
let plaintext = Data("Test message".utf8)
let ciphertext = try aliceSession.encrypt(plaintext)
// First decryption should succeed
@@ -337,7 +337,7 @@ struct NoiseProtocolTests {
try performHandshake(initiator: aliceSession2, responder: bobSession2)
// Encrypt with session 1
let plaintext = "Secret".data(using: .utf8)!
let plaintext = Data("Secret".utf8)
let ciphertext1 = try aliceSession1.encrypt(plaintext)
// Should not be able to decrypt with session 2
@@ -366,10 +366,10 @@ struct NoiseProtocolTests {
try establishManagerSessions(aliceManager: aliceManager, bobManager: bobManager)
// Exchange some messages to establish nonce state
let message1 = try aliceManager.encrypt("Hello".data(using: .utf8)!, for: alicePeerID)
let message1 = try aliceManager.encrypt(Data("Hello".utf8), for: alicePeerID)
_ = try bobManager.decrypt(message1, from: bobPeerID)
let message2 = try bobManager.encrypt("World".data(using: .utf8)!, for: bobPeerID)
let message2 = try bobManager.encrypt(Data("World".utf8), for: bobPeerID)
_ = try aliceManager.decrypt(message2, from: alicePeerID)
// Simulate Bob restart by creating new manager with same key
@@ -391,7 +391,7 @@ struct NoiseProtocolTests {
_ = try aliceManager.handleIncomingHandshake(from: alicePeerID, message: newHandshake3!)
// Should be able to exchange messages with new sessions
let testMessage = "After restart".data(using: .utf8)!
let testMessage = Data("After restart".utf8)
let encrypted = try bobManagerRestarted.encrypt(testMessage, for: bobPeerID)
let decrypted = try aliceManager.decrypt(encrypted, from: alicePeerID)
#expect(decrypted == testMessage)
@@ -409,17 +409,17 @@ struct NoiseProtocolTests {
// Exchange messages to advance nonces
for i in 0..<5 {
let msg = try aliceSession.encrypt("Message \(i)".data(using: .utf8)!)
let msg = try aliceSession.encrypt(Data("Message \(i)".utf8))
_ = try bobSession.decrypt(msg)
}
// Simulate desynchronization by encrypting but not decrypting
for i in 0..<3 {
_ = try aliceSession.encrypt("Lost message \(i)".data(using: .utf8)!)
_ = try aliceSession.encrypt(Data("Lost message \(i)".utf8))
}
// With per-packet nonce carried, decryption should not throw here
let desyncMessage = try aliceSession.encrypt("This now succeeds".data(using: .utf8)!)
let desyncMessage = try aliceSession.encrypt(Data("This now succeeds".utf8))
#expect(throws: Never.self) {
try bobSession.decrypt(desyncMessage)
}
@@ -434,12 +434,11 @@ struct NoiseProtocolTests {
let messageCount = 100
try await confirmation("All messages encrypted and decrypted", expectedCount: messageCount)
{ completion in
try await confirmation("All messages encrypted and decrypted", expectedCount: messageCount) { completion in
var encryptedMessages: [Int: Data] = [:]
// Encrypt messages sequentially to avoid nonce races in manager
for i in 0..<messageCount {
let plaintext = "Concurrent message \(i)".data(using: .utf8)!
let plaintext = Data("Concurrent message \(i)".utf8)
let encrypted = try aliceManager.encrypt(plaintext, for: alicePeerID)
encryptedMessages[i] = encrypted
}
@@ -452,7 +451,7 @@ struct NoiseProtocolTests {
return
}
let decrypted = try bobManager.decrypt(encrypted, from: bobPeerID)
let expected = "Concurrent message \(i)".data(using: .utf8)!
let expected = Data("Concurrent message \(i)".utf8)
#expect(decrypted == expected)
completion()
} catch {
@@ -485,7 +484,7 @@ struct NoiseProtocolTests {
try establishManagerSessions(aliceManager: aliceManager, bobManager: bobManager)
// Create a corrupted message
var encrypted = try aliceManager.encrypt("Test".data(using: .utf8)!, for: alicePeerID)
var encrypted = try aliceManager.encrypt(Data("Test".utf8), for: alicePeerID)
encrypted[10] ^= 0xFF // Corrupt the data
// Decryption should fail
@@ -516,7 +515,7 @@ struct NoiseProtocolTests {
#expect(bobManager.getSession(for: bobPeerID)?.isEstablished() == true)
// Exchange messages to verify sessions work
let testMessage = "Session works".data(using: .utf8)!
let testMessage = Data("Session works".utf8)
let encrypted = try aliceManager.encrypt(testMessage, for: alicePeerID)
let decrypted = try bobManager.decrypt(encrypted, from: bobPeerID)
#expect(decrypted == testMessage)
@@ -539,7 +538,7 @@ struct NoiseProtocolTests {
_ = try bobManager.handleIncomingHandshake(from: bobPeerID, message: newHandshake3!)
// Verify new sessions work
let testMessage2 = "New session works".data(using: .utf8)!
let testMessage2 = Data("New session works".utf8)
let encrypted2 = try aliceManager.encrypt(testMessage2, for: alicePeerID)
let decrypted2 = try bobManager.decrypt(encrypted2, from: bobPeerID)
#expect(decrypted2 == testMessage2)
@@ -555,18 +554,18 @@ struct NoiseProtocolTests {
// Exchange messages normally
for i in 0..<5 {
let msg = try aliceManager.encrypt("Message \(i)".data(using: .utf8)!, for: alicePeerID)
let msg = try aliceManager.encrypt(Data("Message \(i)".utf8), for: alicePeerID)
_ = try bobManager.decrypt(msg, from: bobPeerID)
}
// Simulate desynchronization - Alice sends messages that Bob doesn't receive
for i in 0..<3 {
_ = try aliceManager.encrypt("Lost message \(i)".data(using: .utf8)!, for: alicePeerID)
_ = try aliceManager.encrypt(Data("Lost message \(i)".utf8), for: alicePeerID)
}
// With nonce carried in packet, decryption should not throw here
let desyncMessage = try aliceManager.encrypt(
"This now succeeds".data(using: .utf8)!, for: alicePeerID)
Data("This now succeeds".utf8), for: alicePeerID)
#expect(throws: Never.self) {
try bobManager.decrypt(desyncMessage, from: bobPeerID)
}
@@ -587,7 +586,7 @@ struct NoiseProtocolTests {
_ = try aliceManager.handleIncomingHandshake(from: alicePeerID, message: rehandshake3!)
// Verify communication works again
let testResynced = "Resynced".data(using: .utf8)!
let testResynced = Data("Resynced".utf8)
let encryptedResync = try aliceManager.encrypt(testResynced, for: alicePeerID)
let decryptedResync = try bobManager.decrypt(encryptedResync, from: bobPeerID)
#expect(decryptedResync == testResynced)
@@ -900,20 +899,20 @@ struct NoiseProtocolTests {
#expect(trackingKeychain.secureClearDataCallCount > 0)
// Test encryption from Alice to Bob
let plaintext1 = "Hello from Alice after secureClear!".data(using: .utf8)!
let plaintext1 = Data("Hello from Alice after secureClear!".utf8)
let ciphertext1 = try alice.encrypt(plaintext1)
let decrypted1 = try bob.decrypt(ciphertext1)
#expect(decrypted1 == plaintext1)
// Test encryption from Bob to Alice
let plaintext2 = "Hello from Bob after secureClear!".data(using: .utf8)!
let plaintext2 = Data("Hello from Bob after secureClear!".utf8)
let ciphertext2 = try bob.encrypt(plaintext2)
let decrypted2 = try alice.decrypt(ciphertext2)
#expect(decrypted2 == plaintext2)
// Test multiple messages to verify cipher state is correct
for i in 1...10 {
let msg = "Message \(i) from Alice".data(using: .utf8)!
let msg = Data("Message \(i) from Alice".utf8)
let cipher = try alice.encrypt(msg)
let dec = try bob.decrypt(cipher)
#expect(dec == msg)
@@ -301,7 +301,7 @@ final class PerformanceBaselineTests: XCTestCase {
("@carol#a1b2 did you see this? https://example.com/threads/42", ["carol"]),
("checking in from the harbor #bitchat #mesh", nil),
("@bob#0042 ping me when you get this", ["bob#0042"]),
("long form update with a link https://news.example.org/articles/2026/06/mesh-networks and a tag #geohash", nil),
("long form update with a link https://news.example.org/articles/2026/06/mesh-networks and a tag #geohash", nil)
]
let batches: [[BitchatMessage]] = (0..<batchCount).map { batch in
(0..<batchSize).map { i in
@@ -547,7 +547,7 @@ final class PerformanceBaselineTests: XCTestCase {
"anyone near the station?",
"@bob#0042 are you on mesh too?",
"check this out https://example.com/p/123 #bitchat",
"teleport check, who's local?",
"teleport check, who's local?"
]
return try (0..<count).map { i in
try NostrProtocol.createEphemeralGeohashEvent(
+2 -2
View File
@@ -54,13 +54,13 @@ final class TestHelpers {
type: UInt8 = 0x01,
senderID: PeerID = PeerID(str: UUID().uuidString),
recipientID: PeerID? = nil,
payload: Data = "test payload".data(using: .utf8)!,
payload: Data = Data("test payload".utf8),
signature: Data? = nil,
ttl: UInt8 = 3
) -> BitchatPacket {
return BitchatPacket(
type: type,
senderID: senderID.id.data(using: .utf8)!,
senderID: Data(senderID.id.utf8),
recipientID: recipientID?.id.data(using: .utf8),
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
payload: payload,
+12 -12
View File
@@ -13,7 +13,7 @@ import struct Foundation.Data
struct XChaCha20Poly1305CompatTests {
@Test func sealAndOpenRoundtrip() throws {
let plaintext = "Hello, XChaCha20-Poly1305!".data(using: .utf8)!
let plaintext = Data("Hello, XChaCha20-Poly1305!".utf8)
let key = Data(repeating: 0x42, count: 32)
let nonce = Data(repeating: 0x24, count: 24)
@@ -29,10 +29,10 @@ struct XChaCha20Poly1305CompatTests {
}
@Test func sealAndOpenWithAAD() throws {
let plaintext = "Secret message".data(using: .utf8)!
let plaintext = Data("Secret message".utf8)
let key = Data(repeating: 0xAB, count: 32)
let nonce = Data(repeating: 0xCD, count: 24)
let aad = "additional authenticated data".data(using: .utf8)!
let aad = Data("additional authenticated data".utf8)
let sealed = try XChaCha20Poly1305Compat.seal(plaintext: plaintext, key: key, nonce24: nonce, aad: aad)
let decrypted = try XChaCha20Poly1305Compat.open(
@@ -47,7 +47,7 @@ struct XChaCha20Poly1305CompatTests {
}
@Test func sealProducesDifferentCiphertextWithDifferentNonces() throws {
let plaintext = "Same plaintext".data(using: .utf8)!
let plaintext = Data("Same plaintext".utf8)
let key = Data(repeating: 0x42, count: 32)
let nonce1 = Data(repeating: 0x01, count: 24)
let nonce2 = Data(repeating: 0x02, count: 24)
@@ -59,7 +59,7 @@ struct XChaCha20Poly1305CompatTests {
}
@Test func sealThrowsOnShortKey() {
let plaintext = "Test".data(using: .utf8)!
let plaintext = Data("Test".utf8)
let shortKey = Data(repeating: 0x42, count: 16)
let nonce = Data(repeating: 0x24, count: 24)
@@ -73,7 +73,7 @@ struct XChaCha20Poly1305CompatTests {
}
@Test func sealThrowsOnLongKey() {
let plaintext = "Test".data(using: .utf8)!
let plaintext = Data("Test".utf8)
let longKey = Data(repeating: 0x42, count: 64)
let nonce = Data(repeating: 0x24, count: 24)
@@ -87,7 +87,7 @@ struct XChaCha20Poly1305CompatTests {
}
@Test func sealThrowsOnEmptyKey() {
let plaintext = "Test".data(using: .utf8)!
let plaintext = Data("Test".utf8)
let emptyKey = Data()
let nonce = Data(repeating: 0x24, count: 24)
@@ -116,7 +116,7 @@ struct XChaCha20Poly1305CompatTests {
}
@Test func sealThrowsOnShortNonce() {
let plaintext = "Test".data(using: .utf8)!
let plaintext = Data("Test".utf8)
let key = Data(repeating: 0x42, count: 32)
let shortNonce = Data(repeating: 0x24, count: 12)
@@ -130,7 +130,7 @@ struct XChaCha20Poly1305CompatTests {
}
@Test func sealThrowsOnLongNonce() {
let plaintext = "Test".data(using: .utf8)!
let plaintext = Data("Test".utf8)
let key = Data(repeating: 0x42, count: 32)
let longNonce = Data(repeating: 0x24, count: 32)
@@ -144,7 +144,7 @@ struct XChaCha20Poly1305CompatTests {
}
@Test func sealThrowsOnEmptyNonce() {
let plaintext = "Test".data(using: .utf8)!
let plaintext = Data("Test".utf8)
let key = Data(repeating: 0x42, count: 32)
let emptyNonce = Data()
@@ -173,7 +173,7 @@ struct XChaCha20Poly1305CompatTests {
}
@Test func openFailsWithWrongKey() throws {
let plaintext = "Secret".data(using: .utf8)!
let plaintext = Data("Secret".utf8)
let correctKey = Data(repeating: 0x42, count: 32)
let wrongKey = Data(repeating: 0x43, count: 32)
let nonce = Data(repeating: 0x24, count: 24)
@@ -195,7 +195,7 @@ struct XChaCha20Poly1305CompatTests {
}
@Test func openFailsWithTamperedCiphertext() throws {
let plaintext = "Secret".data(using: .utf8)!
let plaintext = Data("Secret".utf8)
let key = Data(repeating: 0x42, count: 32)
let nonce = Data(repeating: 0x24, count: 24)
+7 -7
View File
@@ -5,16 +5,16 @@ let package = Package(
name: "Tor", // Keep name "Tor" for drop-in compatibility
platforms: [
.iOS(.v16),
.macOS(.v13),
.macOS(.v13)
],
products: [
.library(
name: "Tor",
targets: ["Tor"]
),
)
],
dependencies: [
.package(path: "../BitLogger"),
.package(path: "../BitLogger")
],
targets: [
// Main Swift target
@@ -22,19 +22,19 @@ let package = Package(
name: "Tor",
dependencies: [
"arti",
.product(name: "BitLogger", package: "BitLogger"),
.product(name: "BitLogger", package: "BitLogger")
],
path: "Sources",
exclude: ["C"],
sources: [
"TorManager.swift",
"TorURLSession.swift",
"TorNotifications.swift",
"TorNotifications.swift"
],
linkerSettings: [
.linkedLibrary("resolv"),
.linkedLibrary("z"),
.linkedLibrary("sqlite3"),
.linkedLibrary("sqlite3")
]
),
// Binary framework containing the Rust static library.
@@ -42,6 +42,6 @@ let package = Package(
.binaryTarget(
name: "arti",
path: "Frameworks/arti.xcframework"
),
)
]
)
+1 -1
View File
@@ -21,7 +21,7 @@ let package = Package(
.target(
name: "BitFoundation",
dependencies: [
.product(name: "BitLogger", package: "BitLogger"),
.product(name: "BitLogger", package: "BitLogger")
],
path: "Sources"
),
@@ -46,7 +46,8 @@ struct BinaryProtocolTests {
// Verify recipient
#expect(decodedPacket.recipientID != nil)
let decodedRecipientID = decodedPacket.recipientID?.trimmingNullBytes()
// TODO: Check if this is intended that the decoding only gets the first 8
// Recipient IDs are a fixed 8-byte wire field: encode pads or truncates
// to BinaryProtocol.recipientIDSize, so only the first 8 bytes survive.
#expect(String(data: decodedRecipientID!, encoding: .utf8) == "abcdef01")
}
@@ -294,7 +295,7 @@ struct BinaryProtocolTests {
@Test("Create a large, compressible payload above current threshold (2048B)")
func payloadCompression() throws {
let repeatedString = String(repeating: "This is a test message. ", count: 200)
let largePayload = repeatedString.data(using: .utf8)!
let largePayload = Data(repeatedString.utf8)
let packet = TestHelpers.createTestPacket(payload: largePayload)
@@ -314,7 +315,7 @@ struct BinaryProtocolTests {
@Test("Small payloads should not be compressed")
func smallPayloadNoCompression() throws {
let smallPayload = "Hi".data(using: .utf8)!
let smallPayload = Data("Hi".utf8)
let packet = TestHelpers.createTestPacket(payload: smallPayload)
let encodedData = try #require(BinaryProtocol.encode(packet), "Failed to encode small packet")
let decodedPacket = try #require(BinaryProtocol.decode(encodedData), "Failed to decode small packet")
@@ -362,7 +363,7 @@ struct BinaryProtocolTests {
var encodedSizes = Set<Int>()
for payload in payloads {
let packet = TestHelpers.createTestPacket(payload: payload.data(using: .utf8)!)
let packet = TestHelpers.createTestPacket(payload: Data(payload.utf8))
let encodedData = try #require(BinaryProtocol.encode(packet), "Failed to encode packet")
// Verify padding creates standard block sizes up to configured limit (no 4096 bucket currently)
@@ -54,13 +54,13 @@ final class TestHelpers {
type: UInt8 = 0x01,
senderID: PeerID = PeerID(str: UUID().uuidString),
recipientID: PeerID? = nil,
payload: Data = "test payload".data(using: .utf8)!,
payload: Data = Data("test payload".utf8),
signature: Data? = nil,
ttl: UInt8 = 3
) -> BitchatPacket {
return BitchatPacket(
type: type,
senderID: senderID.id.data(using: .utf8)!,
senderID: Data(senderID.id.utf8),
recipientID: recipientID?.id.data(using: .utf8),
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
payload: payload,