devine-dl/pywidevine

v0 pssh dump when init_data contain key_id

Closed this issue · 2 comments

Describe the bug
Cannot dump v0 pssh when init_data contain key_id

To Reproduce
Steps to reproduce the behavior:

  1. pip install pywidevine
from pywidevine.pssh import PSSH

# v0 pssh not contain key_id
a = 'AAAAR3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAACcIARoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQ='
b = PSSH(a)
print(b.dump().hex())
# dump v0 pssh
# >>000000477073736800000000edef8ba979d64acea3c827dcd51d21ed0000002708011a0d7769646576696e655f746573742210666b6a336c6a61536466616c6b72336a2a024844
print(b.key_ids)
# >>[]
c = PSSH.new(key_ids=None, init_data=b.init_data, version=0, flags=0)
print(c.dump().hex())
# dump v0 pssh
# >>000000477073736800000000edef8ba979d64acea3c827dcd51d21ed0000002708011a0d7769646576696e655f746573742210666b6a336c6a61536466616c6b72336a2a024844
print(c.key_ids)
# >>[]


# v0 pssh contain key_id
d = 'AAAAW3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADsIARIQ62dqu8s0Xpa7z2FmMPGj2hoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQyAA=='
e = PSSH(d)
print(e.dump().hex())
# dump v1 pssh
# >>0000006f7073736801000000edef8ba979d64acea3c827dcd51d21ed00000001eb676abbcb345e96bbcf616630f1a3da0000003b08011210eb676abbcb345e96bbcf616630f1a3da1a0d7769646576696e655f746573742210666b6a336c6a61536466616c6b72336a2a0248443200
print(e.key_ids)
# >>[UUID('eb676abb-cb34-5e96-bbcf-616630f1a3da')]

f = PSSH.new(key_ids=None, init_data=e.init_data, version=0, flags=0)
print(f.dump().hex())
# dump v1 pssh
# >>0000006f7073736801000000edef8ba979d64acea3c827dcd51d21ed00000001eb676abbcb345e96bbcf616630f1a3da0000003b08011210eb676abbcb345e96bbcf616630f1a3da1a0d7769646576696e655f746573742210666b6a336c6a61536466616c6b72336a2a0248443200
print(f.key_ids)
# >>[UUID('eb676abb-cb34-5e96-bbcf-616630f1a3da')]


f.set_key_ids([])
print(f.dump().hex())
# dump v0 pssh but key_id is removed from init_data
# >>000000497073736800000000edef8ba979d64acea3c827dcd51d21ed0000002908011a0d7769646576696e655f746573742210666b6a336c6a61536466616c6b72336a2a0248443200

Expected behavior
all should be dump with v0 pssh

The two first PSSH values you test are both standard v0 PSSH boxes. The only difference with the second one is it's less compliant with deprecation. The second one is the same as the first one but does not have key_id data within the init_data nor the box.

The main issue here is that dump() assumes you want a v1 PSSH (for no reason) as it creates a Box containing both init_data and key_ids. I will make it return the same version PSSH as the input/initialization.

When fixed, the 2nd PSSH dump will still have data in e.key_ids but the version will be correct. key_ids property will still have data as it gets it from both key_IDs within the box, and within the init_data, where possible.

With a very small fix to dump()'s behavior, we get the following results:

>>> from pywidevine import PSSH                                                                                                                  
>>> v0_pssh_no_key_ids = PSSH("AAAAR3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAACcIARoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQ=") 
>>> v0_pssh_key_ids = PSSH("AAAAW3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADsIARIQ62dqu8s0Xpa7z2FmMPGj2hoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQyAA==") 
>>> v0_pssh_no_key_ids.version
0
>>> v0_pssh_key_ids.version
0
>>> PSSH(v0_pssh_no_key_ids.dumps()).dumps() 
'AAAAR3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAACcIARoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQ='
>>> PSSH(v0_pssh_key_ids.dumps()).dumps()    
'AAAAW3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADsIARIQ62dqu8s0Xpa7z2FmMPGj2hoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQyAA=='
>>> PSSH(v0_pssh_no_key_ids.dumps()).version
0
>>> PSSH(v0_pssh_key_ids.dumps()).version
0
>>> PSSH(v0_pssh_no_key_ids.dumps()).key_ids 
[]
>>> PSSH(v0_pssh_key_ids.dumps()).key_ids    
[UUID('eb676abb-cb34-5e96-bbcf-616630f1a3da')]