Add Widevine Key Class
This commit is contained in:
parent
5c9d4cda73
commit
9331f4efc1
|
@ -0,0 +1,63 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import base64
|
||||||
|
from typing import Optional, Union
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
|
from Crypto.Cipher import AES
|
||||||
|
from Crypto.Util import Padding
|
||||||
|
|
||||||
|
from pywidevine.license_protocol_pb2 import License
|
||||||
|
|
||||||
|
|
||||||
|
class Key:
|
||||||
|
def __init__(self, type_: str, kid: UUID, key: bytes, permissions: Optional[list[str]] = None):
|
||||||
|
self.type = type_
|
||||||
|
self.kid = kid
|
||||||
|
self.key = key
|
||||||
|
self.permissions = permissions or []
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return "{name}({items})".format(
|
||||||
|
name=self.__class__.__name__,
|
||||||
|
items=", ".join([f"{k}={repr(v)}" for k, v in self.__dict__.items()])
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_key_container(cls, key: License.KeyContainer, enc_key: bytes) -> Key:
|
||||||
|
"""Load Key from a KeyContainer object."""
|
||||||
|
permissions = []
|
||||||
|
if key.type == License.KeyContainer.KeyType.OPERATOR_SESSION:
|
||||||
|
for descriptor, value in key.operator_session_key_permissions.ListFields():
|
||||||
|
if value == 1:
|
||||||
|
permissions.append(descriptor.name)
|
||||||
|
|
||||||
|
return Key(
|
||||||
|
type_=License.KeyContainer.KeyType.Name(key.type),
|
||||||
|
kid=cls.kid_to_uuid(key.id),
|
||||||
|
key=Padding.unpad(
|
||||||
|
AES.new(enc_key, AES.MODE_CBC, iv=key.iv).decrypt(key.key),
|
||||||
|
16
|
||||||
|
),
|
||||||
|
permissions=permissions
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def kid_to_uuid(kid: Union[str, bytes]) -> UUID:
|
||||||
|
"""
|
||||||
|
Convert a Key ID from a string or bytes to a UUID object.
|
||||||
|
At first this may seem very simple but some types of Key IDs
|
||||||
|
may not be 16 bytes and some may be decimal vs. hex.
|
||||||
|
"""
|
||||||
|
if isinstance(kid, str):
|
||||||
|
kid = base64.b64decode(kid)
|
||||||
|
if not kid:
|
||||||
|
kid = b"\x00" * 16
|
||||||
|
|
||||||
|
if kid.decode(errors="replace").isdigit():
|
||||||
|
return UUID(int=int(kid.decode()))
|
||||||
|
|
||||||
|
if len(kid) < 16:
|
||||||
|
kid += b"\x00" * (16 - len(kid))
|
||||||
|
|
||||||
|
return UUID(bytes=kid)
|
Loading…
Reference in New Issue