+ Only export private key

+ Updated some enums
This commit is contained in:
BuildTools 2024-12-02 18:10:51 +01:00
parent 4ea1fbd1f8
commit c910d1f349
6 changed files with 29 additions and 17 deletions

View File

@ -10,4 +10,4 @@ from .session import *
from .xml_key import * from .xml_key import *
from .xmrlicense import * from .xmrlicense import *
__version__ = "0.4.2" __version__ = "0.4.3"

View File

@ -214,11 +214,6 @@ class Certificate(_BCertStructs):
max_header: int = 15360, max_header: int = 15360,
max_chain_depth: int = 2 max_chain_depth: int = 2
) -> Certificate: ) -> Certificate:
if not cert_id:
raise ValueError("Certificate ID is required")
if not client_id:
raise ValueError("Client ID is required")
basic_info = Container( basic_info = Container(
cert_id=cert_id, cert_id=cert_id,
security_level=security_level, security_level=security_level,
@ -250,9 +245,20 @@ class Certificate(_BCertStructs):
feature = Container( feature = Container(
feature_count=3, feature_count=3,
features=ListContainer([ features=ListContainer([
4, # SECURE_CLOCK # 1, # Transmitter
9, # REVOCATION_LIST_FEATURE # 2, # Receiver
13 # SUPPORTS_PR3_FEATURES # 3, # SharedCertificate
4, # SecureClock
5, # AntiRollBackClock
# 6, # ReservedMetering
# 7, # ReservedLicSync
# 8, # ReservedSymOpt
9, # CRLS (Revocation Lists)
# 10, # ServerBasicEdition
# 11, # ServerStandardEdition
# 12, # ServerPremiumEdition
13, # PlayReady3Features
# 14, # DeprecatedSecureStop
]) ])
) )
feature_attribute = Container( feature_attribute = Container(
@ -385,8 +391,10 @@ class Certificate(_BCertStructs):
return self._BCERT return self._BCERT
def verify_signature(self): def verify_signature(self):
sign_payload = self.dumps()[:-144] signature_object = self.get_attribute(8)
signature_attribute = self.get_attribute(8).attribute signature_attribute = signature_object.attribute
sign_payload = self.dumps()[:-signature_object.length]
raw_signature_key = signature_attribute.signature_key raw_signature_key = signature_attribute.signature_key
signature_key = ECC.construct( signature_key = ECC.construct(

View File

@ -56,15 +56,17 @@ class ECCKey:
with Path(path).open(mode="rb") as f: with Path(path).open(mode="rb") as f:
return cls.loads(f.read()) return cls.loads(f.read())
def dumps(self): def dumps(self, private_only=False):
if private_only:
return self.private_bytes()
return self.private_bytes() + self.public_bytes() return self.private_bytes() + self.public_bytes()
def dump(self, path: Union[Path, str]) -> None: def dump(self, path: Union[Path, str], private_only=False) -> None:
if not isinstance(path, (Path, str)): if not isinstance(path, (Path, str)):
raise ValueError(f"Expecting Path object or path string, got {path!r}") raise ValueError(f"Expecting Path object or path string, got {path!r}")
path = Path(path) path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True) path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(self.dumps()) path.write_bytes(self.dumps(private_only))
def get_point(self, curve: Curve) -> Point: def get_point(self, curve: Curve) -> Point:
return Point(self.key.pointQ.x, self.key.pointQ.y, curve) return Point(self.key.pointQ.x, self.key.pointQ.y, curve)

View File

@ -12,6 +12,7 @@ class Key:
AES_128_ECB = 0x0003 AES_128_ECB = 0x0003
COCKTAIL = 0x0004 COCKTAIL = 0x0004
AES_128_CBC = 0x0005 AES_128_CBC = 0x0005
KEYEXCHANGE = 0x0006
UNKNOWN = 0xffff UNKNOWN = 0xffff
@classmethod @classmethod
@ -24,7 +25,8 @@ class Key:
CHAINED_LICENSE = 0x0002 CHAINED_LICENSE = 0x0002
ECC_256 = 0x0003 ECC_256 = 0x0003
ECC_256_WITH_KZ = 0x0004 ECC_256_WITH_KZ = 0x0004
SCALABLE = 0x0005 TEE_TRANSIENT = 0x0005
ECC_256_VIA_SYMMETRIC = 0x0006
UNKNOWN = 0xffff UNKNOWN = 0xffff
@classmethod @classmethod

View File

@ -279,7 +279,7 @@ def export_device(ctx: click.Context, prd_path: Path, out_dir: Optional[Path] =
if device.group_key: if device.group_key:
group_key_path = out_path / "zgpriv.dat" group_key_path = out_path / "zgpriv.dat"
group_key_path.write_bytes(device.group_key.dumps()) group_key_path.write_bytes(device.group_key.dumps(private_only=True))
log.info("Exported Group Key as zgpriv.dat") log.info("Exported Group Key as zgpriv.dat")
else: else:
log.warning("Cannot export zgpriv.dat, as v2 devices do not save the group key") log.warning("Cannot export zgpriv.dat, as v2 devices do not save the group key")

View File

@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
[tool.poetry] [tool.poetry]
name = "pyplayready" name = "pyplayready"
version = "0.4.2" version = "0.4.3"
description = "pyplayready CDM (Content Decryption Module) implementation in Python." description = "pyplayready CDM (Content Decryption Module) implementation in Python."
license = "CC BY-NC-ND 4.0" license = "CC BY-NC-ND 4.0"
authors = ["DevLARLEY, Erevoc", "DevataDev"] authors = ["DevLARLEY, Erevoc", "DevataDev"]