I tried to create a spotify client for the nintendo switch as my very first rust project. I initially wanted to use librespot as a backend. I gave up pretty quickly, things just went over my head and got too complex.
Yeah, Rust and the Switch don't mesh together very well, at least for now. I was tempted to take that route also, but I ended up reimplementing librespot in C instead, which serves as the backend for this.
Spotify DRM is basically security through obscurity. It's just AES-128-CTR over a plain old OGG file. The tricky part is figuring out the extremely odd protocol you have to request audio keys and track data through. That's all.
Sounds similar to many encrypted HLS streams you see on the internet.
If you're savvy enough to watch the network tab in the browser devtools, you can grab the key and easily decrypt and assemble the chunks. You can even find reference implementations on github (hls.js for instance).
The DRM has been broken for years, and is still broken (I personally wrote a Rust client to grab music from Spotify in .ogg format) but their lawyers rabidly take down any reference to decrypting it on Github or anywhere else, because well, the implication.
It's not, really – AFAIK the audio is just AES-encypted with a per-session key that you get when logging in (but it's been a long time since I looked). There are a bunch of open implementations, like https://github.com/librespot-org/librespot – I guess it's kind of an open secret that you could rip music if you really wanted to, and you certainly used to be able to do that with libspotify when it was still around. I imagine the lawyers will come for you if you're silly enough to bang on about it.
Certainly there's no need for "special hardware decoders" – Spotify works on loads of devices that have no support for that kind of thing.
I don't know how special those decoders could be, obviously not Spotify-specific. Unofficial clients that want to stick around tend to require a premium account, libspotify/spotifyd on Linux for example.
You can download L3 CDM from GitHub, or even dump your own using wvdumper/dumper. Then its just a matter of making a request to Spotify License server, which returns key for decrypting.
I mean, both your PC and your phone will have special DRM-compliant hardware decoders available. Whether Spotify is using those or not is another question, but yes, the CPUs in phones/PCs are equipped to decrypt DRM-secured content.
(one "interesting" case around that was that some OnePlus phones couldn't play netflix in resolutions higher than 480p, because despite the Snapdragon chip supporting the DRM format required for higher resolutions, OnePlus never paid the licence to use it - so their phones couldn't decrypt the video. They did relent later and said they will enable the functionality for users who send in their phones, and it can only be flashed in person at their service centre, not via an OTA update. I always wondered how many people have done that)
they just need to be a less convenient way to pirate music and no one will really bother, a lot of popular music gets pirated before it even hits Spotify anyway
Score one for gbatemp still being around. Don't think I've thought of them since loading ROM fan translations onto your Nintendo DSLite flash-cart was a thing.
Gbatemp once saved me when i bootlooped my friend's phone trying to root it. I needed a stock rom to flash but who the fuck hosts a stock rom for an off-brand android? Turns out some russians do, and a gbatemp user linked it at some point and google scraped it.
Yes, mostly yes, and yes. Early hardware revisions are easily hackable while later ones require a fairly expensive modchip. Games will run stock but depending on what software you load in Nintendo can detect modifications and ban you from online services if you're not careful.
I haven't had any issues on the RE end, mostly because I didn't need to do a whole lot of it, as the librespot people have already paved the way. But I've still gotta figure out the new protocol the Spotify client uses for playlists and such, so... there are bound to be issues up ahead.
Most of my issues stemmed from a lack of proper documentation.
One time I screwed up the packet format and was pulling my hair out when the only response I got was "Invalid username/password" from the Spotify API (or something along those lines. been a while).
The other times were more related to the Switch. Figuring out how networking and audio works, mostly. Hunting through the shit documentation and the source code of libnx to find out what I need to do. My audio implementation was either not playing anything or crashing for a long time in the beginning. I still have no clue what I did to solve it, which is unfortunate.
Yeah, I've realized that the currently used API just lets you request a key for the public Spotify Web API, and I can just get the collection of the user and etc. from there.
I think this is why Spotify will still have a market, even if their upcoming hi-def offering isn't free, such as with Apple or Amazon. The latter two (and all other alternatives, Qobuz and Tidal) don't have an API and so can't be ported to arbitrary platforms; they are only hi-def on Windows, Apple*, and Android.
Strawberry player is supposed to support Tidal, but I can't seem to pull the ClientID/ClientSecret key from the official client (I guess they closed that loophole).
It opened a whole bevvy of open and useful Spotify clients that worked amazingly and some that still do to this day. Mopidy, as well as a handful of amazing MPD-speaking daemons got me through college. The only conceit was that it required a premium account and yielding a third party client your authentication data. They had some issues with Facebook authentication as it was OIDC, but setting a user name and password on your account was a simple solution.
The Spotify team has killed libspotify in preference for a Javascript browser or Mobile Device library (ios/ObjC or Android /kotlin) that uses the browser to authenticate over openID. It can only be a connect target, not query the full api, and depends heavily on the browser or native api to play the media.
Spotify is actually fine with librespot existing (funnily enough, one of the main reasons the old API is still around is that librespot uses it, lol). So, I doubt it will ever get DMCA'd.
Congrats to Mogery for releasing this!
Yeah, Rust and the Switch don't mesh together very well, at least for now. I was tempted to take that route also, but I ended up reimplementing librespot in C instead, which serves as the backend for this.
Yep, the aarch64-nintendo-switch-freestanding target will (very likely) be available in Rust 1.64.0 [0].
[0]: https://github.com/rust-lang/rust/pull/88991#issuecomment-11...
How did was this person able to play the encrypted audio? Does this not let them effectively rip music from Spotify?
If you're savvy enough to watch the network tab in the browser devtools, you can grab the key and easily decrypt and assemble the chunks. You can even find reference implementations on github (hls.js for instance).
Certainly there's no need for "special hardware decoders" – Spotify works on loads of devices that have no support for that kind of thing.
"The good old days"
[1] Trace of this, from 2013: https://stackoverflow.com/questions/20614360/does-the-libspo...
Can you play Spotify on your PC or phone?
(one "interesting" case around that was that some OnePlus phones couldn't play netflix in resolutions higher than 480p, because despite the Snapdragon chip supporting the DRM format required for higher resolutions, OnePlus never paid the licence to use it - so their phones couldn't decrypt the video. They did relent later and said they will enable the functionality for users who send in their phones, and it can only be flashed in person at their service centre, not via an OTA update. I always wondered how many people have done that)
Most of my issues stemmed from a lack of proper documentation.
One time I screwed up the packet format and was pulling my hair out when the only response I got was "Invalid username/password" from the Spotify API (or something along those lines. been a while).
The other times were more related to the Switch. Figuring out how networking and audio works, mostly. Hunting through the shit documentation and the source code of libnx to find out what I need to do. My audio implementation was either not playing anything or crashing for a long time in the beginning. I still have no clue what I did to solve it, which is unfortunate.
I think you can just see what Spot [0] does instead!
[0] https://github.com/xou816/spot
Strawberry player is supposed to support Tidal, but I can't seem to pull the ClientID/ClientSecret key from the official client (I guess they closed that loophole).
It opened a whole bevvy of open and useful Spotify clients that worked amazingly and some that still do to this day. Mopidy, as well as a handful of amazing MPD-speaking daemons got me through college. The only conceit was that it required a premium account and yielding a third party client your authentication data. They had some issues with Facebook authentication as it was OIDC, but setting a user name and password on your account was a simple solution.
The Spotify team has killed libspotify in preference for a Javascript browser or Mobile Device library (ios/ObjC or Android /kotlin) that uses the browser to authenticate over openID. It can only be a connect target, not query the full api, and depends heavily on the browser or native api to play the media.
I assume it's inevitable, with the fervour of people in the switch homebrew scene.