From 23c766af7188d730af36d33c15ca61ceecaedd6b Mon Sep 17 00:00:00 2001 From: rlaphoenix Date: Sat, 3 Sep 2022 19:43:31 +0100 Subject: [PATCH] Cdm: Improve accuracy of OEMCrypto request_id research The main change is that it isn't stored as 16-bytes. Effectively not stored like it realistically probably meant to be. It's instead stored as a hex string that was then encoded to bytes (32 data is now taken up). But I've also improved the comments about my research for the first half of the request ID. This research is likely still incomplete as I'm just not fully sure about the randomness of bytes 5-8. --- pywidevine/cdm.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pywidevine/cdm.py b/pywidevine/cdm.py index b1a6493..d3aa9f8 100644 --- a/pywidevine/cdm.py +++ b/pywidevine/cdm.py @@ -280,7 +280,14 @@ class Cdm: raise InvalidLicenseType(f"License Type {type_!r} is invalid") if self.device_type == Device.Types.ANDROID: - request_id = get_random_bytes(8) + session.number.to_bytes(8, "little") + # OEMCrypto's request_id seems to be in AES CTR Counter block form with no suffix + # Bytes 5-8 does not seem random, in real tests they have been consecutive \x00 or \xFF + # Real example: A0DCE548000000000500000000000000 + request_id = (get_random_bytes(4) + (b"\x00" * 4)) # (?) + request_id += session.number.to_bytes(8, "little") # counter + # as you can see in the real example, it is stored as uppercase hex and re-encoded + # it's really 16 bytes of data, but it's stored as a 32-char HEX string (32 bytes) + request_id = request_id.hex().upper().encode() else: request_id = get_random_bytes(16)