Unify PeerIDUtils & PeerIDResolver in Peer

This commit is contained in:
islam
2025-09-20 01:26:19 +01:00
parent 9be05f98e9
commit 7b20bdf821
7 changed files with 28 additions and 45 deletions
+20
View File
@@ -7,6 +7,7 @@
// //
import Foundation import Foundation
import struct CryptoKit.SHA256
struct Peer: Equatable, Hashable { struct Peer: Equatable, Hashable {
let id: String let id: String
@@ -111,3 +112,22 @@ extension Peer {
self.init(str: str) self.init(str: str)
} }
} }
// MARK: - Noise Public Key Helpers
extension Peer {
/// Derive the stable 16-hex peer ID from a Noise static public key
init(publicKey: Data) {
let digest = SHA256.hash(data: publicKey)
let hex = digest.map { String(format: "%02x", $0) }.joined()
self.init(str: hex.prefix(16))
}
/// Returns a 16-hex short peer ID derived from a 64-hex Noise public key if needed
func toShort() -> Peer {
if id.count == Constants.maxIDLength, let data = Data(hexString: id) {
return Peer(publicKey: data)
}
return self
}
}
+1 -1
View File
@@ -100,7 +100,7 @@ struct NostrEmbeddedBitChat {
if let maybeData = Data(hexString: recipientPeerID) { if let maybeData = Data(hexString: recipientPeerID) {
if maybeData.count == 32 { if maybeData.count == 32 {
// Treat as Noise static public key; derive peerID from fingerprint // Treat as Noise static public key; derive peerID from fingerprint
return PeerIDUtils.derivePeerID(fromPublicKey: maybeData) return Peer(publicKey: maybeData).id
} else if maybeData.count == 8 { } else if maybeData.count == 8 {
// Already an 8-byte peer ID // Already an 8-byte peer ID
return recipientPeerID return recipientPeerID
-14
View File
@@ -1,14 +0,0 @@
import Foundation
import CryptoKit
// MARK: - Peer ID Utilities
struct PeerIDUtils {
/// Derive the stable 16-hex peer ID from a Noise static public key
static func derivePeerID(fromPublicKey publicKey: Data) -> String {
let digest = SHA256.hash(data: publicKey)
let hex = digest.map { String(format: "%02x", $0) }.joined()
return String(hex.prefix(16))
}
}
+3 -13
View File
@@ -556,23 +556,13 @@ final class BLEService: NSObject {
func isPeerConnected(_ peerID: String) -> Bool { func isPeerConnected(_ peerID: String) -> Bool {
// Accept both 16-hex short IDs and 64-hex Noise keys // Accept both 16-hex short IDs and 64-hex Noise keys
let shortID: String = { let shortID = Peer(str: peerID).toShort().id
if peerID.count == 64, let key = Data(hexString: peerID) {
return PeerIDUtils.derivePeerID(fromPublicKey: key)
}
return peerID
}()
return collectionsQueue.sync { peers[shortID]?.isConnected ?? false } return collectionsQueue.sync { peers[shortID]?.isConnected ?? false }
} }
func isPeerReachable(_ peerID: String) -> Bool { func isPeerReachable(_ peerID: String) -> Bool {
// Accept both 16-hex short IDs and 64-hex Noise keys // Accept both 16-hex short IDs and 64-hex Noise keys
let shortID: String = { let shortID = Peer(str: peerID).toShort().id
if peerID.count == 64, let key = Data(hexString: peerID) {
return PeerIDUtils.derivePeerID(fromPublicKey: key)
}
return peerID
}()
return collectionsQueue.sync { return collectionsQueue.sync {
// Must be mesh-attached: at least one live direct link to the mesh // Must be mesh-attached: at least one live direct link to the mesh
let meshAttached = peers.values.contains { $0.isConnected } let meshAttached = peers.values.contains { $0.isConnected }
@@ -1518,7 +1508,7 @@ final class BLEService: NSObject {
// Verify that the sender's derived ID from the announced noise public key matches the packet senderID // Verify that the sender's derived ID from the announced noise public key matches the packet senderID
// This helps detect relayed or spoofed announces. Only warn in release; assert in debug. // This helps detect relayed or spoofed announces. Only warn in release; assert in debug.
let derivedFromKey = PeerIDUtils.derivePeerID(fromPublicKey: announcement.noisePublicKey) let derivedFromKey = Peer(publicKey: announcement.noisePublicKey).id
if derivedFromKey != peerID { if derivedFromKey != peerID {
SecureLogger.warning("⚠️ Announce sender mismatch: derived \(derivedFromKey.prefix(8))… vs packet \(peerID.prefix(8))", category: .security) SecureLogger.warning("⚠️ Announce sender mismatch: derived \(derivedFromKey.prefix(8))… vs packet \(peerID.prefix(8))", category: .security)
@@ -182,9 +182,8 @@ final class FavoritesPersistenceService: ObservableObject {
func getFavoriteStatus(forPeerID peerID: String) -> FavoriteRelationship? { func getFavoriteStatus(forPeerID peerID: String) -> FavoriteRelationship? {
// Quick sanity: peerID should be 16 hex chars (8 bytes) // Quick sanity: peerID should be 16 hex chars (8 bytes)
guard peerID.count == 16 else { return nil } guard peerID.count == 16 else { return nil }
for (pubkey, rel) in favorites { for (pubkey, rel) in favorites where Peer(publicKey: pubkey).id == peerID {
let derived = PeerIDUtils.derivePeerID(fromPublicKey: pubkey) return rel
if derived == peerID { return rel }
} }
return nil return nil
} }
+2 -2
View File
@@ -21,7 +21,7 @@ final class MessageRouter {
) { [weak self] note in ) { [weak self] note in
guard let self = self else { return } guard let self = self else { return }
if let data = note.userInfo?["peerPublicKey"] as? Data { if let data = note.userInfo?["peerPublicKey"] as? Data {
let peerID = PeerIDUtils.derivePeerID(fromPublicKey: data) let peerID = Peer(publicKey: data).id
Task { @MainActor in Task { @MainActor in
self.flushOutbox(for: peerID) self.flushOutbox(for: peerID)
} }
@@ -29,7 +29,7 @@ final class MessageRouter {
// Handle key updates // Handle key updates
if let newKey = note.userInfo?["peerPublicKey"] as? Data, if let newKey = note.userInfo?["peerPublicKey"] as? Data,
let _ = note.userInfo?["isKeyUpdate"] as? Bool { let _ = note.userInfo?["isKeyUpdate"] as? Bool {
let peerID = PeerIDUtils.derivePeerID(fromPublicKey: newKey) let peerID = Peer(publicKey: newKey).id
Task { @MainActor in Task { @MainActor in
self.flushOutbox(for: peerID) self.flushOutbox(for: peerID)
} }
-12
View File
@@ -1,12 +0,0 @@
import Foundation
struct PeerIDResolver {
/// Returns a 16-hex short peer ID derived from a 64-hex Noise public key if needed
static func toShortID(_ id: String) -> String {
if id.count == 64, let data = Data(hexString: id) {
return PeerIDUtils.derivePeerID(fromPublicKey: data)
}
return id
}
}