mirror of
				https://github.com/devine-dl/pywidevine.git
				synced 2025-11-04 03:44:50 +00:00 
			
		
		
		
	Add Widevine Key Class
This commit is contained in:
		
							parent
							
								
									5c9d4cda73
								
							
						
					
					
						commit
						9331f4efc1
					
				
							
								
								
									
										63
									
								
								pywidevine/key.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								pywidevine/key.py
									
									
									
									
									
										Normal file
									
								
							@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user