Posted by Amir Mazzarella on February 24, 2018
I finished yet another project a few days ago: pymsl
. You can find the link here: https://github.com/truedread/pymsl. Of course, it's not nearly as popular as my Chrome extension, but that's just because it's not meant for an end-user; it's intended for someone like me who likes to poke Netflix in different ways. What this Python library allows you to do is communicate with the Netflix MSL API to obtain manifests for a list of viewable IDs or obtain licenses for the same list. In making this project, however, I found some bugs in Netflix's MSL implementation. MSL is open-source—here's the link: https://github.com/Netflix/msl. MSL itself isn't buggy; it's Netflix's implementation that is. For example, if you try to obtain manifests with "primetime" as the DRM system, Netflix will throw an error when trying to find initialization data that matches the primetime system ID. Also, if one tries to load licenses for multiple viewable IDs like one can with manifests, he or she will find it impossible due to playback context IDs not being accepted as a list in the license request. Thus, if you try to obtain licenses for multiple viewable IDs, you'll get duplicate licenses for the viewable ID that matches the single playback context ID you provided. My library gets around this by wrapping the license requests in a loop to make it easier for the end-user, but if Netflix accepted playback context IDs as a list, it would be the best solution.
If you're curious, considering my library can be quite a doozy to read, the steps for completing an MSL key exchange are as follows:
Construct a header containing the sender (ESN), whether or not this is a key exchange (the first step is always a key exchange), timestamp, public RSA key, message ID, and client capabilities.
Construct another JSON containing the entity authentication data and wrap the header into it as headerdata
.
Send a POST request to the MSL manifest URL with the POST data being the JSON you constructed in step 2.
Parse the response for the mastertoken, encrypted encryption key, and encrypted sign key, and decrypt both keys with your RSA private key that corresponds with the public key you sent in the key exchange.
The decrypted encryption key and sign key will be webcrypto objects serialized to JSON strings, so parse them accordingly and make sure to pad the URL safe base64 encoded key.
Congratulations, you've communicated with the MSL API. The MSL wiki on GitHub is quite informative, even if it doesn't contain all the details you need to interact with the Netflix implementation. Luckily, my library handles most of the headaches for you, and if it fails on something, make sure to create a GitHub issue, and I'll look into it promptly!