[GH-ISSUE #495] Zeroconf based Authentication by command line #315

Closed
opened 2026-02-27 19:29:58 +03:00 by kerem · 11 comments
Owner

Originally created by @jgabriel98 on GitHub (Jun 16, 2020).
Original GitHub issue: https://github.com/librespot-org/librespot/issues/495

I want to mock (simulate) a connection to the lib by code, with the zeroconf authentication mode.

In other words, i want to run a librespot instance, and then connect to it as a "spotify connect" device, but using code or cli, not the spotify app.

is this possible?

Originally created by @jgabriel98 on GitHub (Jun 16, 2020). Original GitHub issue: https://github.com/librespot-org/librespot/issues/495 I want to mock (simulate) a connection to the lib by code, with the [zeroconf authentication mode](https://github.com/librespot-org/librespot/blob/master/docs/authentication.md#zeroconf-based-authentication). In other words, i want to run a librespot instance, and then connect to it as a "spotify connect" device, but using code or cli, not the spotify app. is this possible?
kerem 2026-02-27 19:29:58 +03:00
Author
Owner

@noelhibbard commented on GitHub (Jul 8, 2020):

I'm looking to do something similar. My goal is to programmatically swap which account the librespot instance is associated with. The document you referenced above explains how the auth blob is decoded but I need to know how to encode a blob which I would then use for zeroconf auth.

<!-- gh-comment-id:655696957 --> @noelhibbard commented on GitHub (Jul 8, 2020): I'm looking to do something similar. My goal is to programmatically swap which account the librespot instance is associated with. The document you referenced above explains how the auth blob is decoded but I need to know how to encode a blob which I would then use for zeroconf auth.
Author
Owner

@idcmp commented on GitHub (Jan 11, 2021):

I have a similar need. I've got a Spotify Connect device at http://192.168.1.118/spotify that I would like to programatically run "addUser" on from one of two accounts. Calls to kick the current user off: curl -d action=resetUsers http://192.168.1.118/spotify and get details about the device curl -d action=getInfo http://192.168.1.118/spotify work fine, but similar to @noelhibbard I'm not quite sure how to craft a "blob"

<!-- gh-comment-id:758204920 --> @idcmp commented on GitHub (Jan 11, 2021): I have a similar need. I've got a Spotify Connect device at http://192.168.1.118/spotify that I would like to programatically run "addUser" on from one of two accounts. Calls to kick the current user off: `curl -d action=resetUsers http://192.168.1.118/spotify` and get details about the device `curl -d action=getInfo http://192.168.1.118/spotify` work fine, but similar to @noelhibbard I'm not quite sure how to craft a "blob"
Author
Owner

@noelhibbard commented on GitHub (Jan 11, 2021):

I'm not super knowledgeable on encryption but I'm thinking you would need the private key to construct the blob and all we have is the public key for decrypting the blob. As far as I know, only the official Spotify clients are capable of initiating a zero config auth. If there is an open source project that can handle that side of the process then we could look at that for hints but I don't think one exists.

<!-- gh-comment-id:758209380 --> @noelhibbard commented on GitHub (Jan 11, 2021): I'm not super knowledgeable on encryption but I'm thinking you would need the private key to construct the blob and all we have is the public key for decrypting the blob. As far as I know, only the official Spotify clients are capable of initiating a zero config auth. If there is an open source project that can handle that side of the process then we could look at that for hints but I don't think one exists.
Author
Owner

@idcmp commented on GitHub (Jan 13, 2021):

@plietar - I see you're the author of the zeroconf authentication page. Can you offer up any details on how to generate blobs? Whose private key do I need to do the DH exchange?

<!-- gh-comment-id:759252634 --> @idcmp commented on GitHub (Jan 13, 2021): @plietar - I see you're the author of the zeroconf authentication page. Can you offer up any details on how to generate blobs? Whose private key do I need to do the DH exchange?
Author
Owner

@ashthespy commented on GitHub (Jan 13, 2021):

In the odd case you haven't already seen the docs on zeroconf..

<!-- gh-comment-id:759381179 --> @ashthespy commented on GitHub (Jan 13, 2021): In the odd case you haven't already seen the [docs](https://github.com/librespot-org/librespot/blob/dev/docs/authentication.md#zeroconf-based-authentication) on zeroconf..
Author
Owner

@noelhibbard commented on GitHub (Jan 13, 2021):

Those docs only explain how you decrypt a blob. We are trying to do the opposite.

<!-- gh-comment-id:759397531 --> @noelhibbard commented on GitHub (Jan 13, 2021): Those docs only explain how you decrypt a blob. We are trying to do the opposite.
Author
Owner

@ashthespy commented on GitHub (Jan 13, 2021):

Ah fair enough, sorry for the noise :-)

<!-- gh-comment-id:759400726 --> @ashthespy commented on GitHub (Jan 13, 2021): Ah fair enough, sorry for the noise :-)
Author
Owner

@plietar commented on GitHub (Jan 13, 2021):

@idcmp with DH, both sides have a private and a public key. They exchange public keys to compute a shared secret.

  • Generate a random private key
  • Compute the corresponding public key
  • Fetch the device's public key using getInfo
  • Combine your private key with the device's public key to obtain the shared secret
  • Compute the encryption and checksum key. The docs look like they have some typos and don't match exactly what the code does (especially around the slicing the key bit). In doubt the code is more reliable.
  • Encrypt the blob using AES128-CTR and a random 16 byte IV.
  • Compute the mac of the encrypted blob using hmac-sha1
  • Concatenate the IV, mac and encrypted blob and send that to the device.

To actually compute the blob, you'd have to implement this function, backwards. There seem to be a couple of fields in the unencrypted blob that aren't described. I'm not sure what these are. Running librespot and printing their values could help.

<!-- gh-comment-id:759448447 --> @plietar commented on GitHub (Jan 13, 2021): @idcmp with DH, both sides have a private and a public key. They exchange public keys to compute a shared secret. - Generate a random private key - Compute the corresponding public key - Fetch the device's public key using `getInfo` - Combine your private key with the device's public key to obtain the shared secret - Compute the encryption and checksum key. The docs look like they have some typos and don't match exactly what [the code does](https://github.com/librespot-org/librespot/blob/06f5aa9c907f6702ecba4147d6291c1cc448b295/connect/src/discovery.rs#L113-L126) (especially around the slicing the key bit). In doubt the code is more reliable. - Encrypt the blob using AES128-CTR and a random 16 byte IV. - Compute the mac of the encrypted blob using hmac-sha1 - Concatenate the IV, mac and encrypted blob and send that to the device. ---- To actually compute the blob, you'd have to implement [this function](https://github.com/librespot-org/librespot/blob/06f5aa9c907f6702ecba4147d6291c1cc448b295/core/src/authentication.rs#L40), backwards. There seem to be a couple of fields in the unencrypted blob that aren't described. I'm not sure what these are. Running librespot and printing their values could help.
Author
Owner

@idcmp commented on GitHub (Jan 14, 2021):

Got it. Sorry if this is a stupid question, is github.com/librespot-org/librespot@06f5aa9c90/core/src/authentication.rs (L92-L95) just doing the CTR (except the last 16 bytes?)?

As listed in:

blob = AES128-CTR-DECRYPT(encryption_key, IV, encrypted)
<!-- gh-comment-id:759912992 --> @idcmp commented on GitHub (Jan 14, 2021): Got it. Sorry if this is a stupid question, is https://github.com/librespot-org/librespot/blob/06f5aa9c907f6702ecba4147d6291c1cc448b295/core/src/authentication.rs#L92-L95 just doing the CTR (except the last 16 bytes?)? As listed in: ``` blob = AES128-CTR-DECRYPT(encryption_key, IV, encrypted) ```
Author
Owner

@plietar commented on GitHub (Jan 14, 2021):

That piece of code corresponds to the login_data = AES192-DECRYPT(key, data) line in the docs.

The code is a naive manual translation from the disassembled binary to Rust. I’m no crypto expert, so I have a hard time identifying the “high level” algorithms.

It is certainly not CTR, since it is XORing pieces of the plaintext together, rather than the plaintext with some AES stream. On the other hand, it doesn’t match any of the other common cipher modes.

<!-- gh-comment-id:760219433 --> @plietar commented on GitHub (Jan 14, 2021): That piece of code corresponds to the `login_data = AES192-DECRYPT(key, data)` line in the docs. The code is a naive manual translation from the disassembled binary to Rust. I’m no crypto expert, so I have a hard time identifying the “high level” algorithms. It is certainly not CTR, since it is XORing pieces of the plaintext together, rather than the plaintext with some AES stream. On the other hand, it doesn’t match any of the other common cipher modes.
Author
Owner

@devgianlu commented on GitHub (Jan 14, 2021):

You can have a look at the Java implementation too: github.com/librespot-org/librespot-java@1c9537a2a2/lib/src/main/java/xyz/gianlu/librespot/core/Session.java (L867)

<!-- gh-comment-id:760489431 --> @devgianlu commented on GitHub (Jan 14, 2021): You can have a look at the Java implementation too: https://github.com/librespot-org/librespot-java/blob/1c9537a2a21833d68491f8bda077606fe1120c75/lib/src/main/java/xyz/gianlu/librespot/core/Session.java#L867
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/librespot#315
No description provided.