accessory: Integrate .plist reading into library

This commit is contained in:
Mike A
2024-04-25 19:37:01 +02:00
parent 184c5b822b
commit fe534931cf
2 changed files with 30 additions and 33 deletions

View File

@@ -3,13 +3,11 @@ Example showing how to fetch locations of an AirTag, or any other FindMy accesso
"""
from __future__ import annotations
import plistlib
from datetime import datetime, timedelta, timezone
from pathlib import Path
from _login import get_account_sync
from findmy import FindMyAccessory, KeyPair
from findmy import FindMyAccessory
from findmy.reports import RemoteAnisetteProvider
# URL to (public or local) anisette server
@@ -18,37 +16,11 @@ ANISETTE_SERVER = "http://localhost:6969"
# Path to a .plist dumped from the Find My app.
PLIST_PATH = Path("airtag.plist")
# == The variables below are auto-filled from the plist!! ==
with PLIST_PATH.open("rb") as f:
device_data = plistlib.load(f)
# PRIVATE master key. 28 (?) bytes.
MASTER_KEY = device_data["privateKey"]["key"]["data"][-28:]
# "Primary" shared secret. 32 bytes.
SKN = device_data["sharedSecret"]["key"]["data"]
# "Secondary" shared secret. 32 bytes.
SKS = device_data["secondarySharedSecret"]["key"]["data"]
# "Paired at" timestamp (UTC)
PAIRED_AT = device_data["pairingDate"].replace(tzinfo=timezone.utc)
def _gen_keys(airtag: FindMyAccessory, _from: datetime, to: datetime) -> set[KeyPair]:
keys = set()
while _from < to:
keys.update(airtag.keys_at(_from))
_from += timedelta(minutes=15)
return keys
def main() -> None:
# Step 0: create an accessory key generator
airtag = FindMyAccessory(MASTER_KEY, SKN, SKS, PAIRED_AT)
with PLIST_PATH.open("rb") as f:
airtag = FindMyAccessory.from_plist(f)
# Step 1: log into an Apple account
print("Logging into account")

View File

@@ -6,9 +6,10 @@ Accessories could be anything ranging from AirTags to iPhones.
from __future__ import annotations
import logging
import plistlib
from abc import ABC, abstractmethod
from datetime import datetime, timedelta
from typing import Generator, overload
from datetime import datetime, timedelta, timezone
from typing import IO, Generator, overload
from typing_extensions import override
@@ -143,6 +144,30 @@ class FindMyAccessory(RollingKeyPairSource):
return possible_keys
@classmethod
def from_plist(cls, plist: IO[bytes]) -> FindMyAccessory:
"""Create a FindMyAccessory from a .plist file dumped from the FindMy app."""
device_data = plistlib.load(plist)
# PRIVATE master key. 28 (?) bytes.
master_key = device_data["privateKey"]["key"]["data"][-28:]
# "Primary" shared secret. 32 bytes.
skn = device_data["sharedSecret"]["key"]["data"]
# "Secondary" shared secret. 32 bytes.
if "secondarySharedSecret" in device_data:
# AirTag
sks = device_data["secondarySharedSecret"]["key"]["data"]
else:
# iDevice
sks = device_data["secureLocationsSharedSecret"]["key"]["data"]
# "Paired at" timestamp (UTC)
paired_at = device_data["pairingDate"].replace(tzinfo=timezone.utc)
return cls(master_key, skn, sks, paired_at)
class AccessoryKeyGenerator(KeyGenerator[KeyPair]):
"""KeyPair generator. Uses the same algorithm internally as FindMy accessories do."""