MENU

使用 Find My 实时位置查询 API

April 7, 2026 • Read: 2 • Linux

使用 Find My 实时位置查询 API

通过本教程,你可以搭建一个 HTTP API,实时查询 Apple Find My 设备(包括 AirTag)的位置,支持逆地理编码地址显示。

最终效果

curl -H "X-API-Key: your-key" http://your-server:8000/items/airtag-name/address
# 返回:时代广场, 1 Matheson Street, 銅鑼灣 Causeway Bay, 香港 Hong Kong

整体架构

┌─────────────────────────────────────────────────────────┐
│                    你的服务器 (Linux/Mac)                │
│                                                         │
│   findmy_api (FastAPI)                                 │
│   ├── Apple Account Session (account.json)              │
│   ├── FindMyAccessory Keys (accessories/*.json)        │
│   └── Nominatim 逆地理编码                             │
└──────────────┬──────────────────────────────────────────┘
               │ Apple API (HTTPS)
               ▼
        Apple Find My Server

注意:整个方案需要一台 Mac 来提取密钥。服务器可以是 Linux。


核心原理

Find My 加密体系

Apple Find My 使用非对称加密保护设备隐私:

  1. Master Key:设备配对时生成的 EC 私钥(28字节),设备端永不联网
  2. SKN / SKS:基于时间的滚动对称密钥(每15分钟轮换),用于加密位置报告
  3. advertisedLocationId:公开广播的公钥哈希,用于在 Apple 服务器查找设备

位置报告流程:

设备广播 → 用 SKS 加密位置 → 上传 Apple 服务器
              ↓
查询者 → Apple API → 用 Master Key 派生解密密钥 → 解密位置报告

只有持有 Master Key 才能解密位置报告,这就是为什么需要从 Mac 提取密钥。

为什么需要 Mac?

BeaconStoreKey 和 accessory Master Key 都存储在 macOS Keychain 中,受 SIP/AMFI 保护。提取需要:

  1. SIP disabled — 允许 lldb 附加到 Apple 系统进程
  2. AMFI disabled — 允许读取受保护的系统密钥

两个关键工具

1. findmy-key-extractor

提取三组 Find My 加密密钥:

密钥用途加密方式
LocalStorage.key解密 LocalStorage.dbAES-256 XOR
FMIPDataManager.bplist设备/物品/成员缓存ChaCha20-Poly1305
FMFDataManager.bplist朋友元数据缓存ChaCha20-Poly1305

通过 lldb 附加到 findmylocateagentFindMy.app 进程,在密钥传递到系统函数时从寄存器中截取。

2. beaconstorekey-extractor

提取 BeaconStore AES-256 密钥,用于解密 searchpartyd.record 文件。

这些文件中包含每个设备的 Master Key(即 FindMyAccessory.from_plist() 需要的 privateKeysharedSecretsecondarySharedSecret)。

从 macOS Tahoe (26+) 开始,searchpartyd 数据从:

~/Library/com.apple.icloud.searchpartyd/

迁移到了:

~/Library/Group Containers/group.com.apple.icloud.searchpartyuseragent/Library/Storage/

需要手动修改源码中的路径。


提取流程

第一步:禁用 SIP

  1. 重启进入 Recovery Mode
  2. 终端运行:csrutil disable
  3. 重启后添加启动参数:sudo nvram boot-args="amfi_get_out_of_my_way=1"
  4. 再重启

第二步:提取 BeaconStoreKey

git clone https://github.com/pajowu/beaconstorekey-extractor.git
cd beaconstorekey-extractor
make run
# 输出类似:<your-beaconstore-key>

保存这个64字符的 hex 字符串。

第三步:解密 beacon 数据

macOS Tahoe+ 需要先修改 searchpartyd-decryptor.swift 中的路径:

let basePath = "Group Containers/group.com.apple.icloud.searchpartyuseragent/Library/Storage"

重新编译后运行,输入 BeaconStoreKey,Finder 会打开解密后的文件。

也可以用 Python 脚本解密:

from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import plistlib

BEACONSTORE_KEY = bytes.fromhex("你的hex字符串")
# .record 文件格式:[nonce(16字节), tag(16字节), ciphertext]

aesgcm = AESGCM(BEACONSTORE_KEY)
decrypted = aesgcm.decrypt(nonce, ciphertext + tag, associated_data=None)
data = plistlib.loads(decrypted)
# data 包含 privateKey, sharedSecret, secondarySharedSecret

解密后 OwnedBeacons/ 目录下的文件包含各设备的 Master Key。

第四步:转换为 FindMyAccessory JSON

FindMy.py 的格式导出:

from findmy import FindMyAccessory

accessory = FindMyAccessory.from_plist({
    "privateKey": beacon["privateKey"],
    "sharedSecret": beacon["sharedSecret"],
    "secondarySharedSecret": beacon["secondarySharedSecret"],
    "pairingDate": beacon["pairingDate"],
    "model": beacon.get("model", ""),
    "identifier": beacon["identifier"],
})
accessory.to_json(f"{name}.json")

生成 accessories/*.json 文件集。

第五步:生成 Apple 会话

用于 Apple 服务器认证:

pip install findmy python-dotenv
python scripts/bootstrap_account.py

生成 account.json

第六步:重新启用 SIP

# 重启进入 Recovery Mode
csrutil enable
nvram -d boot-args

服务器部署

Linux 需要 anisette 远程服务

LocalAnisetteProvider 使用 macOS 系统缓存,仅 macOS 可用。Linux 需要远程 anisette 服务:

# 在 Mac 上运行
git clone https://github.com/Dadoum/ anisette-server.git
python anisette-server.py

然后在 Linux 服务器设置:

FINDMY_ANISETTE_SERVER=http://Mac-IP:端口

启动服务

pip install fastapi uvicorn pydantic python-dotenv findmy

uvicorn findmy_api.main:app --host 0.0.0.0 --port 8000

API 接口

接口说明
GET /items列出所有设备
GET /items/{name}设备详情(含地址)
GET /items/{name}/location实时坐标
GET /items/{name}/address逆地理编码地址

所有接口需要 header:X-API-Key: your-key


隐私说明

  • account.json:Apple 账号会话,请妥善保管
  • accessories/*.json:设备私钥,等同于设备本身
  • 建议使用强 API Key,并启用 HTTPS

参考