VT-PR/vinetrimmer/utils/MSL/schemes/PlayReadyKeyExchangeScheme.py
2025-04-29 11:54:44 +05:30

111 lines
3.5 KiB
Python

import base64
import json
import os
from Cryptodome.Cipher import AES, PKCS1_OAEP
from Cryptodome.Hash import HMAC, SHA256
from Cryptodome.Random import get_random_bytes
from Cryptodome.Util import Padding
from vinetrimmer.utils.MSL.schemes.KeyExchangeRequest import KeyExchangeRequest
class PlayReady(KeyExchangeRequest):
"""
Implementation of the PlayReady Key Exchange Scheme for MSL.
"""
def __init__(self):
self.encryption_key = None
self.sign_key = None
self.sender = None
def perform_key_exchange(self, session, endpoint, sender, cdm):
"""
Performs a key exchange using PlayReady.
Parameters:
session: HTTP session with necessary cookies
endpoint: Endpoint for key exchange
sender: ESN of the device
cdm: CDM instance
"""
self.sender = sender
# Generate random keys for encryption and signing
self.encryption_key = get_random_bytes(16) # AES-128
self.sign_key = get_random_bytes(32) # HMAC-SHA256
# Return keys in the format required by MSL
return {
"encryptionkey": base64.b64encode(self.encryption_key).decode("utf-8"),
"hmackey": base64.b64encode(self.sign_key).decode("utf-8")
}
def encrypt(self, data, encryption_envelope=None):
"""
Encrypts data using the encryption key.
Parameters:
data: Data to encrypt
encryption_envelope: Not used in PlayReady
"""
if not self.encryption_key:
raise ValueError("No encryption key available")
# Generate a random IV
iv = get_random_bytes(16)
# Encrypt the data
cipher = AES.new(self.encryption_key, AES.MODE_CBC, iv)
ciphertext = cipher.encrypt(Padding.pad(data.encode("utf-8"), 16))
# Return encrypted data in the format required by MSL
return {
"keyid": self.sender,
"iv": base64.b64encode(iv).decode("utf-8"),
"ciphertext": base64.b64encode(ciphertext).decode("utf-8")
}
def decrypt(self, data):
"""
Decrypts data using the encryption key.
Parameters:
data: Encrypted data (with iv and ciphertext)
"""
if not self.encryption_key:
raise ValueError("No encryption key available")
# Decode IV and ciphertext
iv = base64.b64decode(data["iv"])
ciphertext = base64.b64decode(data["ciphertext"])
# Decrypt the data
cipher = AES.new(self.encryption_key, AES.MODE_CBC, iv)
plaintext = Padding.unpad(cipher.decrypt(ciphertext), 16)
return plaintext
def sign(self, data):
"""
Signs data using the sign key.
Parameters:
data: Data to sign
"""
if not self.sign_key:
raise ValueError("No sign key available")
# Sign the data with HMAC-SHA256
signature = HMAC.new(self.sign_key, data.encode("utf-8"), SHA256).digest()
return base64.b64encode(signature)
def verify(self, data, signature):
"""
Verifies a signature.
Parameters:
data: Data that was signed
signature: Signature to verify
"""
expected_signature = self.sign(data)
return signature == expected_signature.decode("utf-8")