Files
location-spoofer/Shared/CoreBridge.swift
T
xweiba c8aba2be78 release: PaopaoLocationSpoofer v1.0.0
- iOS 虚拟定位工具,基于本地 HTTP 代理 MITM 方案
- MapKit 原生地图体验,支持搜索、收藏、实时定位
- 完整的设置引导流程(证书安装、WiFi 代理配置、环境验证)
- 支持 iOS 15+,SwiftUI 构建
2026-08-05 15:45:24 +08:00

127 lines
4.8 KiB
Swift

import Foundation
import Darwin
struct CertificateAuthority: Equatable {
let certPEM: String
let keyPEM: String
}
enum CoreBridgeError: LocalizedError {
case generationFailed
case serverStartFailed
var errorDescription: String? {
switch self {
case .generationFailed: return "无法生成本地证书"
case .serverStartFailed: return "无法启动本地证书服务"
}
}
}
enum CoreBridge {
static func generateCertificateAuthority() throws -> CertificateAuthority {
RuntimeLogger.info("APP", "Core.CA", "调用 Go Core 生成 CA")
let result = wloccore_generateca()
guard let certPointer = result.r0, let keyPointer = result.r1 else {
flushLogs(category: "CA")
throw CoreBridgeError.generationFailed
}
defer { free(certPointer); free(keyPointer) }
RuntimeLogger.info("APP", "Core.CA", "Go Core CA 生成成功")
flushLogs(category: "CA")
return CertificateAuthority(certPEM: String(cString: certPointer), keyPEM: String(cString: keyPointer))
}
/// 调用 Go Core 做一次模拟 wloc 响应改写测试,验证定位数据是否会被改成目标坐标。
static func testWlocPatch(lat: Double, lon: Double, accuracy: Int) -> String {
guard let ptr = wloccore_testpatch(CDouble(lat), CDouble(lon), CInt(accuracy)) else {
return "error: null result"
}
defer { free(ptr) }
return String(cString: ptr)
}
/// 构造接近真实设备格式的 wloc 请求体(多个 WiFi AP + 蜂窝基站)。
static func testWlocRequestData() -> Data {
guard let ptr = wloccore_testrequesthex() else { return Data([0x0a, 0x02, 0x08, 0x01]) }
defer { free(ptr) }
let hex = String(cString: ptr)
var data = Data()
var idx = hex.startIndex
while idx < hex.endIndex {
let end = hex.index(idx, offsetBy: 2, limitedBy: hex.endIndex) ?? hex.endIndex
if let b = UInt8(hex[idx..<end], radix: 16) { data.append(b) }
idx = end
}
return data
}
static func flushLogs(category: String) {
guard let pointer = wloccore_drainlogs() else { return }
defer { free(pointer) }
String(cString: pointer).split(separator: "\n").forEach {
RuntimeLogger.info("CORE", category, String($0))
}
}
static func refreshVerifyToken() -> String {
guard let ptr = wloccore_refreshverifytoken() else { return "" }
defer { free(ptr) }
return String(cString: ptr)
}
}
final class LocalCertificateServer {
private var handle: UInt = 0
private(set) var downloadURL: URL?
private(set) var probeURL: URL?
private(set) var leafHash = ""
deinit { stop() }
func start(authority: CertificateAuthority) throws {
if handle != 0 {
RuntimeLogger.debug("APP", "Certificate.server", "本地证书服务已在运行")
return
}
RuntimeLogger.info("APP", "Certificate.server", "调用 Go Core 启动本地证书服务")
let newHandle: UInt = authority.certPEM.withCString { certPointer in
authority.keyPEM.withCString { keyPointer in
UInt(wloccore_startcertserver(UnsafeMutablePointer(mutating: certPointer), UnsafeMutablePointer(mutating: keyPointer)))
}
}
guard newHandle != 0 else {
CoreBridge.flushLogs(category: "CertificateServer")
throw CoreBridgeError.serverStartFailed
}
let httpPort = Int(wloccore_certserver_httpport(newHandle))
let httpsPort = Int(wloccore_certserver_httpsport(newHandle))
guard httpPort > 0, httpsPort > 0, let hashPointer = wloccore_certserver_leafsha256(newHandle) else {
_ = wloccore_stopcertserver(newHandle)
throw CoreBridgeError.serverStartFailed
}
defer { free(hashPointer) }
handle = newHandle
downloadURL = URL(string: "http://127.0.0.1:\(httpPort)/ca.cer")
probeURL = URL(string: "https://127.0.0.1:\(httpsPort)/health")
leafHash = String(cString: hashPointer)
RuntimeLogger.info("APP", "Certificate.server", "本地证书服务启动成功", details: [
"httpPort": String(httpPort),
"httpsPort": String(httpsPort),
"leafHash": leafHash
])
CoreBridge.flushLogs(category: "CertificateServer")
}
func stop() {
guard handle != 0 else { return }
let result = wloccore_stopcertserver(handle)
RuntimeLogger.info("APP", "Certificate.server", "停止本地证书服务", details: ["result": String(result)])
CoreBridge.flushLogs(category: "CertificateServer")
handle = 0
downloadURL = nil
probeURL = nil
leafHash = ""
}
}