applecontinuity

package
v0.663.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 9, 2026 License: AGPL-3.0 Imports: 4 Imported by: 0

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).

type Result

type Result struct {
	Messages    []Message `json:"messages"`
	MessageCnt  int       `json:"message_count"`
	TotalBytes  int       `json:"total_bytes_decoded"`
	Summary     string    `json:"summary"`
	OuterFormat string    `json:"outer_format"`
}

Result is the top-level decoded view.

func Decode

func Decode(hexStr string) (*Result, error)

Decode parses an Apple Continuity payload from hex.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL