Documentation
¶
Overview ¶
Package applecontinuity decodes Apple Continuity BLE advertisement payloads — the Manufacturer-Specific-Data blob Apple devices broadcast for Handoff, AirDrop, Nearby Info / Action, AirPods proximity pairing, iBeacon, Hey Siri, and the other ad-hoc connectivity primitives that make the Apple ecosystem feel "magical" on a sniffer.
Wrap-vs-native judgement
Native. The Continuity protocol is undocumented by Apple but has been extensively reverse-engineered: Mertens et al. (furiousMAC, 2019), Stute et al. (TU Darmstadt 2019- 2024), AppleJuice, hexway/apple_bleee, and the Wireshark dissectors all converge on the same TLV structure and the same per-type field semantics. The wire format is a tight Type/Length/Value walker — no crypto, no variable-length integers, no compression at this layer. Operators paste the Manufacturer Specific Data bytes (post-Apple-Company-ID 0x004C) from a Wireshark BLE capture, a Sniffle/CatSniffer dump, an hcidump trace, or any BLE scanner and inspect every documented field.
What this package covers
Outer envelope tolerance: the input may be the raw TLV stream (e.g. "1005...10 05..."), the post-CompanyID manufacturer data ("4C00 10 05..."), or the full advertising-data record ("0BFF4C00 10 05..."). The walker auto-detects each form and strips down to the TLV bytes.
TLV walking: each message inside the stream is (Type[1] + Length[1] + Value[Length]). Multiple messages per advertisement are common (e.g. Nearby Info + Handoff frequently appear together).
Type table (per furiousMAC + AppleJuice + Wireshark): 0x02 iBeacon (RFC-equivalent: Apple's own spec, publicly documented as the iBeacon protocol) 0x03 AirPrint 0x04 AirDrop 0x05 HomeKit 0x06 Proximity Pairing (AirPods / Beats / etc.) 0x07 Hey Siri 0x08 AirPlay Source 0x09 AirPlay Target 0x0A Magic Switch (Apple Pencil) 0x0B Watch Connection 0x0C Handoff 0x0D WiFi Settings Target 0x0E Tethering Target (Instant Hotspot) 0x0F Nearby Action 0x10 Nearby Info
Per-type body decoding (best-effort, headline fields):
iBeacon (0x02, length 21): UUID (16 bytes hex) + Major (uint16 BE) + Minor (uint16 BE) + TX Power (int8 dBm). The canonical Apple-issued spec.
Handoff (0x0C, variable): Clipboard-state byte + IV (2 bytes) + AuthTag (1 byte) + Encrypted Payload.
Nearby Info (0x10, variable): high nibble of byte 0 = StatusFlags, low nibble = ActionCode (15-entry name table); byte 1 = DataFlags; remaining bytes = AuthTag.
Nearby Action (0x0F, variable): ActionFlags byte
ActionType byte (15-entry name table for setup flows: Wi-Fi join, AirPods setup, HomePod auto-setup, Apple TV setup, etc.) + AuthTag + optional ActionParameters.
AirDrop (0x04, length 18): Status byte + 8 bytes of Apple ID / phone / email hash material.
Proximity Pairing (0x06, variable): Device model byte
status flags + battery levels (Left + Right + Case for AirPods) + UTP (Unknown Transport Pairing) + Lid state.
Hey Siri (0x07, length 5): Hash bytes used to wake Siri across devices.
Other types: surfaced with Type + TypeName + Length
raw hex body. Operators who need full dissection of AirPlay, HomeKit, or Watch frames can read the bytes.
Multi-TLV summary: a per-advertisement summary string (e.g. "Nearby Info + Handoff") for triage.
What this package does NOT cover (deliberately out of scope)
The BLE Link-Layer / Advertising PDU framing — that's `ble_classify` / `ble_findmy_*`.
The AppleID / phone / email / OfflineFinding key reversal — encrypted material is surfaced as hex; the decryption side belongs in a separate Spec.
Handoff payload decryption — IV + AuthTag are surfaced but the cipher-text is opaque without the pairing key.
The Bluetooth Low Energy GAP / GATT layer beyond the advertising data record.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Encode ¶ added in v0.388.0
func Encode(r EncodeRequest) ([]byte, error)
Encode builds the raw bytes of an Apple Continuity message — the inverse of Decode. Currently the iBeacon message (type 0x02) is supported, round-trip-verified against Decode.
Wrap-vs-native judgement ¶
Native, and the inverse of the existing decoder. The iBeacon layout is Apple's public, universally-implemented format (company ID 0x004C, message type 0x02, length 0x15: 16-byte proximity UUID + big-endian major + big-endian minor + signed measured-power byte); encoding is pure byte assembly — no crypto, no hardware. It produces the manufacturer-data payload an operator advertises from a beacon (e.g. a spoofed iBeacon for a proximity test); generation only, no BLE TX, so it is Low risk like the decoder. Correctness is verifiable two ways: round-trip against Decode and the fixed iBeacon byte layout (02 15 <uuid> <major> <minor> <tx>).
Deliberately deferred ¶
The other Continuity message types are not encodable here: Handoff (0x0C), NearbyInfo (0x10), AirDrop (0x04), Proximity Pairing (0x06), and Hey-Siri (0x07) carry encrypted bodies / auth tags / device-derived hashes the operator cannot synthesise offline, and Nearby Action (0x0F) is the device-popup BLE-spam primitive this project does not generate by policy. iBeacon is the one Continuity message that is a clean, public, non-cryptographic deterministic layout.
Types ¶
type AirDrop ¶
type AirDrop struct {
StatusHex string `json:"status_hex"`
IdentifierHex string `json:"identifier_hex"`
}
AirDrop is the body of message type 0x04.
type EncodeRequest ¶ added in v0.388.0
type EncodeRequest struct {
Kind string `json:"kind"`
// iBeacon fields (kind=ibeacon).
UUID string `json:"uuid,omitempty"`
Major uint16 `json:"major,omitempty"`
Minor uint16 `json:"minor,omitempty"`
TXPower int8 `json:"tx_power_dbm,omitempty"`
// Wrap controls the framing of the returned bytes:
// "" / "tlv" — the bare Continuity TLV (type, length, body);
// the default.
// "manufacturer" — prefixed with the 0x4C 0x00 Apple Company ID
// (the manufacturer-data payload).
// "ad" — the full advertising-data record
// (<len>, 0xFF, 0x4C, 0x00, TLV) ready to drop
// into an advertising payload.
Wrap string `json:"wrap,omitempty"`
}
EncodeRequest describes one Apple Continuity message to build. Kind selects the message type. Currently "ibeacon" (type 0x02) is supported — the one Continuity message whose body is a fully deterministic, non-cryptographic, public layout.
type Handoff ¶
type Handoff struct {
ClipboardStatus string `json:"clipboard_status"`
IVHex string `json:"iv_hex"`
AuthTagHex string `json:"auth_tag_hex"`
PayloadHex string `json:"encrypted_payload_hex"`
}
Handoff is the body of message type 0x0C.
type HeySiri ¶
type HeySiri struct {
HashHex string `json:"hash_hex"`
}
HeySiri is the body of message type 0x07.
type IBeacon ¶
type IBeacon struct {
UUID string `json:"uuid"`
Major uint16 `json:"major"`
Minor uint16 `json:"minor"`
TXPower int8 `json:"tx_power_dbm"`
}
IBeacon is the body of message type 0x02.
type Message ¶
type Message struct {
Type int `json:"type"`
TypeHex string `json:"type_hex"`
TypeName string `json:"type_name"`
Length int `json:"length"`
BodyHex string `json:"body_hex,omitempty"`
IBeacon *IBeacon `json:"ibeacon,omitempty"`
Handoff *Handoff `json:"handoff,omitempty"`
NearbyInfo *NearbyInfo `json:"nearby_info,omitempty"`
NearbyAction *NearbyAction `json:"nearby_action,omitempty"`
AirDrop *AirDrop `json:"airdrop,omitempty"`
HeySiri *HeySiri `json:"hey_siri,omitempty"`
ProxPairing *ProxPairing `json:"proximity_pairing,omitempty"`
}
Message is one decoded Continuity TLV entry.
type NearbyAction ¶
type NearbyAction struct {
ActionFlags int `json:"action_flags"`
ActionType int `json:"action_type"`
ActionTypeName string `json:"action_type_name"`
AuthTagHex string `json:"auth_tag_hex,omitempty"`
ParametersHex string `json:"parameters_hex,omitempty"`
}
NearbyAction is the body of message type 0x0F.
type NearbyInfo ¶
type NearbyInfo struct {
StatusFlags int `json:"status_flags"`
StatusBits string `json:"status_bits_decoded"`
ActionCode int `json:"action_code"`
ActionName string `json:"action_name"`
DataFlags int `json:"data_flags,omitempty"`
AuthTagHex string `json:"auth_tag_hex,omitempty"`
}
NearbyInfo is the body of message type 0x10.
type ProxPairing ¶
type ProxPairing struct {
DeviceModel int `json:"device_model"`
DeviceModelHex string `json:"device_model_hex"`
StatusFlags int `json:"status_flags"`
BatteryLeft int `json:"battery_left_pct,omitempty"`
BatteryRight int `json:"battery_right_pct,omitempty"`
BatteryCase int `json:"battery_case_pct,omitempty"`
LidState int `json:"lid_state,omitempty"`
RawHex string `json:"raw_hex,omitempty"`
}
ProxPairing is the body of message type 0x06 (AirPods / Beats).