Crypto primitives for AirPlay 2 pairing + the encrypted channel, mapping the
AirPlay 2 scheme onto Erlang :crypto:
- HKDF-SHA512 (RFC 5869) — key derivation for pair-setup/verify + the session.
- ChaCha20-Poly1305 AEAD — the encrypted control channel + audio packets.
- X25519 ECDH + Ed25519 — used by legacy/HomeKit
pair-verify.
See the protocol notes for the salts/infos and where each is used.
Summary
Functions
Inverse of audio_encrypt/3 (for tests): payload is ct<>tag16<>nonce8.
Encrypt one AP2 audio packet payload (ChaChaPoly), porting AirPlayClientV2. Encrypt: a per-packet 12-byte nonce <<0::32, rand64::64>>, AEAD over pcm
with aad (the RTP header), and the random 8 nonce bytes appended as a trailer
so the receiver can reconstruct the nonce. Returns ciphertext <> tag16 <> nonce8.
ChaCha20-Poly1305 decrypt → plaintext or :error.
ChaCha20-Poly1305 encrypt → {ciphertext, tag16}.
Generate an Ed25519 keypair {public, private}.
Ed25519 signature over message with private key.
Verify an Ed25519 signature over message with public key.
HKDF-SHA512: extract+expand ikm to len bytes with salt/info.
Generate an X25519 keypair {public, private} (32 bytes each).
X25519 ECDH shared secret from our private + peer public key.
Functions
Inverse of audio_encrypt/3 (for tests): payload is ct<>tag16<>nonce8.
Encrypt one AP2 audio packet payload (ChaChaPoly), porting AirPlayClientV2. Encrypt: a per-packet 12-byte nonce <<0::32, rand64::64>>, AEAD over pcm
with aad (the RTP header), and the random 8 nonce bytes appended as a trailer
so the receiver can reconstruct the nonce. Returns ciphertext <> tag16 <> nonce8.
ChaCha20-Poly1305 decrypt → plaintext or :error.
ChaCha20-Poly1305 encrypt → {ciphertext, tag16}.
Generate an Ed25519 keypair {public, private}.
Ed25519 signature over message with private key.
Verify an Ed25519 signature over message with public key.
@spec hkdf(binary(), binary(), binary(), pos_integer()) :: binary()
HKDF-SHA512: extract+expand ikm to len bytes with salt/info.
Generate an X25519 keypair {public, private} (32 bytes each).