// // OpenHaystack – Tracking personal Bluetooth devices via Apple's Find My network // // Copyright © 2021 Secure Mobile Networking Lab (SEEMOO) // Copyright © 2021 The Open Wireless Link Project // // SPDX-License-Identifier: AGPL-3.0-only // import Combine import Foundation import SwiftUI class FindMyController: ObservableObject { static let shared = FindMyController() @Published var error: Error? @Published var devices = [FindMyDevice]() func loadPrivateKeys( from data: Data, with searchPartyToken: Data, completion: @escaping (Error?) -> Void ) { do { let devices = try PropertyListDecoder().decode([FindMyDevice].self, from: data) self.devices.append(contentsOf: devices) self.fetchReports(with: searchPartyToken, completion: completion) } catch { self.error = FindMyErrors.decodingPlistFailed(message: String(describing: error)) } } func importReports(reports: [FindMyReport], and keys: Data, completion: @escaping () -> Void) throws { var devices = try PropertyListDecoder().decode([FindMyDevice].self, from: keys) // Decrypt the reports with the imported keys DispatchQueue.global(qos: .background).async { // Add the reports to the according device by finding the right key for the report for report in reports { guard let deviceIndex = devices.firstIndex(where: { (device) -> Bool in device.keys.contains { (key) -> Bool in key.hashedKey.base64EncodedString() == report.id } }) else { print("No device found for id") continue } if var reports = devices[deviceIndex].reports { reports.append(report) devices[deviceIndex].reports = reports } else { devices[deviceIndex].reports = [report] } } self.devices = devices // Decrypt the reports self.decryptReports { self.exportDevices() DispatchQueue.main.async { completion() } } } } func importDevices(devices: Data) throws { var devices = try PropertyListDecoder().decode([FindMyDevice].self, from: devices) // Delete the decrypted reports for idx in devices.startIndex.. Void) { DispatchQueue.global(qos: .background).async { let fetchReportGroup = DispatchGroup() let fetcher = ReportsFetcher() var devices = self.devices for deviceIndex in 0.. Void) { print("Decrypting reports") // Iterate over all devices for deviceIdx in 0..