# Connection Setup
## Access point Connection
The first step to connecting to Spotify's servers is finding an Access Point (AP) to do so.
Clients make an HTTP GET request to `http://apresolve.spotify.com` to retrieve a list of hostname an port combination in JSON format.
An AP is randomly picked from that list to connect to.

The connection is done using a bare TCP socket. Despite many APs using ports 80 and 443, neither HTTP nor TLS are used to connect.

If `http://apresolve.spotify.com` is unresponsive, `ap.spotify.com:443` is used as a fallback.

## Connection Hello
The first 3 packets exchanged are unencrypted, and have the following format :

header   | length | payload
---------|--------|---------
variable |   32   | variable

Length is a 32 bit, big endian encoded, integer.
It is the length of the entire packet, ie `len(header) + 4 + len(payload)`.

The header is only present in the very first packet sent by the client, and is two bytes long, `[0, 4]`.
It probably corresponds to the protocol version used.

The payload is a protobuf encoded message.

The client starts by sending a `ClientHello` message, describing the client info, a random nonce and client's Diffie Hellman public key.

The AP replies by a `APResponseMessage` message, containing a random nonce and the server's DH key.

The client solves a challenge based on these two packets, and sends it back using a `ClientResponsePlaintext`.
It also computes the shared keys used to encrypt the rest of the communication.

## Login challenge and cipher key computation.
The client starts by computing the DH shared secret using it's private key and the server's public key.
HMAC-SHA1 is then used to compute the send and receive keys, as well as the login challenge.

```
data = []
for i in 1..6 {
    data += HMAC(client_hello || ap_response || [ i ], shared)
}

challenge = HMAC(client_hello || ap_response, data[:20])
send_key = data[20:52]
recv_key = data[52:84]
```

`client_hello` and `ap_response` are the first packets sent respectively by the client and the AP.
These include the header and length fields.

## Encrypted packets
Every packet after ClientResponsePlaintext is encrypted using a Shannon cipher.

The cipher is setup with 4 bytes big endian nonce, incremented after each packet, starting at zero.
Two independent ciphers and accompanying nonces are used, one for transmission and one for reception,
using respectively `send_key` and `recv_key` as keys.

The packet format is as followed :

cmd | length | payload  | mac
----|--------|----------|----
 8  |   16   | variable | 32

Each packet has a type identified by the 8 bit `cmd` field.
The 16 bit big endian length only includes the length of the payload.