extracting radiko v8's API key

This was done with version 8.0.6. The methods detailed here may have been patched out since (but probably haven't).

method

Download the APK and open it as a ZIP file. Then go to /assets/flutter_assets/assets/key/ - and lo and behold, there it is.

It's stored as android.jpg, and as you can see it is in fact a JPG image. There's also ios.jpg, which is identical, and annex_poc.jpg, which is slightly different. I don't know what annex means here, but I assume poc is short for Proof of Concept.

you can use this mitmproxy script to confirm that it's real:

from mitmproxy import http
import base64

class key_stealer:
	def response(self, flow):
		if "X-Radiko-KeyLength" in flow.response.headers:
#			flow.response.headers["X-Radiko-KeyLength"] = "16000"
			flow.response.headers["X-Radiko-KeyLength"] = "125779"
			flow.response.headers["X-Radiko-KeyOffset"] = "0"

	def request(self, flow):
		if "X-Radiko-Partialkey" in flow.request.headers:
			header_value = flow.request.headers["X-Radiko-Partialkey"]
			print(header_value)
			with open('fullkey', 'wb') as f:
				f.write(base64.b64decode(header_value))

addons = [
	key_stealer()
]

What that does, is it changes the headers sent by auth1 so that it requests the whole key - 125779 bytes, starting from byte 0.
Then, the app replies to that, it takes that whole key the app is sending, and writes it to disk.

run it like this: mitmweb --ignore-hosts connectivitycheck.gstatic.com -s mitmproxy-key-stealer.py.
The ignore connectivitycheck bit is important, otherwise android will think there's no internet connection.

I also got the device info from mitmproxy:

X-Radiko-App: aSmartPhone8
X-Radiko-Device: android
User-Agent: Mozilla/5.0 (Linux; Android 10; Pixel 4 XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Mobile Safari/537.36
my phone's not a pixel and it runs android 9 lol, it seems the user agent is hardcoded
but that's good because it means I don't have to do anything clever for the impersonation, I can just hardcode it as well

backstory/how this came to pass

I wanted the v8 key for resilience/to ensure the continued functionality of my plugin.
The v7 aSmartPhone7a key is fairly widely distributed- every tool that impersonates the app, AFAIK does it as v7. If radiko decides to crack down and revoke the v7 key, we're fucked.
So I decided to try and get the key from the current version, which no one is impersonating. That way, if they do revoke v7, I can just switch over to v8 and keep going as normal.

I was looking around in the APK to see if there was anything interesting in there, and oh look, that's an interesting looking directory
I thought maybe it was obfuscated at first, or the app derived the real key from the image somehow - surely, they can't have just left it there?
I assumed the key had to be 16KB in size, as that's what the v7 key was. I didn't have any way to actually tell, as my phone was too old to run the new app lol

Conveniently(?) my phone finally died/stopped working as a telephone around that time, so I had to get a new one anyway.
I installed the radiko app, and with a bit of help from the chat gpt, I wrote the mitmproxy script above.

well would you look at that it was just the jpg after all

At time of writing (13th april 2024), the v7 key hasn't been revoked, so yt-dlp-rajiko continues to use that. But if/when it is revoked, I'll be ready.