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 from __future__ import annotations
import plistlib
from datetime import datetime, timedelta, timezone
from pathlib import Path from pathlib import Path
from _login import get_account_sync from _login import get_account_sync
from findmy import FindMyAccessory, KeyPair from findmy import FindMyAccessory
from findmy.reports import RemoteAnisetteProvider from findmy.reports import RemoteAnisetteProvider
# URL to (public or local) anisette server # 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. # Path to a .plist dumped from the Find My app.
PLIST_PATH = Path("airtag.plist") 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: def main() -> None:
# Step 0: create an accessory key generator # 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 # Step 1: log into an Apple account
print("Logging into account") print("Logging into account")

View File

@@ -6,9 +6,10 @@ Accessories could be anything ranging from AirTags to iPhones.
from __future__ import annotations from __future__ import annotations
import logging import logging
import plistlib
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from datetime import datetime, timedelta from datetime import datetime, timedelta, timezone
from typing import Generator, overload from typing import IO, Generator, overload
from typing_extensions import override from typing_extensions import override
@@ -143,6 +144,30 @@ class FindMyAccessory(RollingKeyPairSource):
return possible_keys 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]): class AccessoryKeyGenerator(KeyGenerator[KeyPair]):
"""KeyPair generator. Uses the same algorithm internally as FindMy accessories do.""" """KeyPair generator. Uses the same algorithm internally as FindMy accessories do."""