3
äb`§<  ã               @   sÚ   d dl Z d dlZd dlZd dlZd dlZd dlmZ d dlmZ d dl	m
Z
 d dl	mZ d dlmZmZ d dlmZmZmZmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlm Z  G dd„ dƒZ!dS )é    N)ÚDecodeError)Útext_format)Úget_random_bytes)Úrandom)Ú
PKCS1_OAEPÚAES)ÚCMACÚSHA256ÚHMACÚSHA1)ÚRSA)Úpss)ÚPadding)Úwv_proto2_pb2)ÚSession)ÚKeyc               @   sN   e Zd Zdd„ Zddd„Zdd„ Zd	d
„ Zdd„ Zdd„ Zdd„ Z	dd„ Z
dS )ÚCdmc             C   s   t jtƒ| _i | _d S )N)ÚloggingÚ	getLoggerÚ__name__ÚloggerÚsessions)Úself© r   ú:C:\Users\Broad\Desktop\BeinConnetFix\pywidevine\cdm\cdm.pyÚ__init__   s    zCdm.__init__NFc             C   sö   | j jdj||ƒƒ | j jdƒ |jdkrbdjdd„ tdƒD ƒƒ}d}d	}|| | }|jd
ƒ}n(|jdkrztdƒ}	|	}n| j j	dƒ dS |r¨t
|ttfƒr¨|}
d| _n| j|ƒ}
d| _|
rÌt||
||ƒ}n| j j	dƒ dS || j|< | j jdƒ |S )Nz(open_session(init_data_b64={}, device={}zopening new cdm sessionZandroidÚ c             s   s   | ]}t jd ƒV  qdS )ZABCDEF0123456789N)r   Úchoice)Ú.0Ú_r   r   r   ú	<genexpr>    s    z#Cdm.open_session.<locals>.<genexpr>é   Z01Z00000000000000ÚasciiZchromezdevice type is unusableé   TFzunable to parse init dataz0session opened and init data parsed successfully)r   ÚdebugÚformatÚinfoZsession_id_typeÚjoinÚrangeÚencoder   ÚerrorÚ
isinstanceÚbytesÚ	bytearrayÚraw_psshÚ_parse_init_datar   r   )r   Úinit_data_b64ZdeviceZraw_init_dataÚofflineZ
rand_asciiZcounterÚrestÚ
session_idZ
rand_bytesÚ	init_dataZnew_sessionr   r   r   Úopen_session   s2    



zCdm.open_sessionc             C   sÄ   t jƒ }y(| jjdƒ |jtj|ƒdd … ƒ W n^ tk
rŽ   | jjdƒ y|jtj|ƒdd … ƒ}W n  tk
rˆ   | jjdƒ d S X Y nX | jjdƒ x"t	j
|ƒjƒ D ]}| jj|ƒ q¬W |S )Nz"trying to parse init_data directlyé    z:unable to parse as-is, trying with removed pssh box headerz-unable to parse, unsupported init data formatz
init_data:)Ú	wv_proto2ZWidevineCencHeaderr   r$   ÚParseFromStringÚbase64Ú	b64decoder   r*   r   ÚMessageToStringÚ
splitlines)r   r0   Zparsed_init_dataZid_bytesÚliner   r   r   r/   =   s    zCdm._parse_init_datac             C   s^   | j jdj|ƒƒ | j jdƒ || jkrD| jj|ƒ | j jdƒ dS | j jdj|ƒƒ dS d S )Nzclose_session(session_id={})zclosing cdm sessionzcdm session closedr   zsession {} not foundr#   )r   r$   r%   r&   r   Úpop)r   r3   r   r   r   Úclose_sessionN   s    
zCdm.close_sessionc             C   sV  | j jdj||ƒƒ | j jdƒ || jkr:| j jdƒ dS | j| }tjƒ }y|jt	j
|ƒƒ W n  tk
r€   | j jdƒ Y nX tjƒ }|jrÐ| j jdƒ y|j|jƒ W n  tk
rÌ   | j jdƒ dS X nD| j jdƒ y|jt	j
|ƒƒ W n" tk
�r   | j jdƒ dS X | j jd	ƒ x$tj|ƒjƒ D ]}| j j|ƒ �q0W ||_d
|_dS )Nz/set_service_certificate(session_id={}, cert={})zsetting service certificatezsession id doesn't existr#   z%failed to parse cert as SignedMessagez&service cert provided as signedmessagez#failed to parse service certificatez0service cert provided as signeddevicecertificatezservice certificate:Tr   )r   r$   r%   r&   r   r*   r7   ZSignedMessager8   r9   r:   r   ZSignedDeviceCertificateÚTypeÚMsgr   r;   r<   Úservice_certificateÚprivacy_mode)r   r3   Zcert_b64ÚsessionÚmessagerB   r=   r   r   r   Úset_service_certificateY   s>    

zCdm.set_service_certificatec          "   C   sø  | j jdj|ƒƒ | j jdƒ || jkr8| j jdƒ dS | j| }| jrRtjƒ }ntj	ƒ }tj
ƒ }tjj|jjƒs‚| j jdƒ dS t|jjdƒ�:}y|j|jƒ ƒ}W n  tk
rÄ   | j jdƒ dS X W d Q R X | j jdƒ | j�s
tj	jjd	ƒ|_|jjjjj|jƒ ntjjjd	ƒ|_|j|jjj_|j�r>tjjd
ƒ}ntjjdƒ}||jjj_||jjj_tj j!jdƒ|j_t"t#j#ƒ ƒ|j_$tj%jdƒ|j_%|jj&�r®t'j(ddƒ|j_)|j*�r|jj+�r<| j jdƒ | j jdƒ tj,ƒ }t|jj-dƒ�<}y|j|jƒ ƒ}	W n" tk
�r$   | j jdƒ dS X W d Q R X |j.j|ƒ | j jdƒ | j jdƒ x$t/j0|ƒj1ƒ D ]}
| j j|
ƒ �qdW t2dƒ}t2dƒ}t3j4|t3j5|ƒ}|j6t7j8|j9ƒ dƒƒ}t:j;|j<j=j>ƒ}t?j4|ƒ}|j6|ƒ}tj@ƒ }|j<j=jA|_A|j<j=jB|_C||_D||_E||_F|jjDj|ƒ n|jjGj|ƒ |jjH�rLt:j;t|jjIƒjƒ ƒ}||_Jn| j jdƒ dS | j jdƒ tKj4|jj9ƒ ƒ}tLj4|ƒjM|ƒ}||_N||_O| j jdƒ x&t/j0|jOƒj1ƒ D ]}
| j j|
ƒ �q²W | j jdƒ | j jdjtPjQ|j9ƒ ƒƒƒ |j9ƒ S )Nz"get_license_request(session_id={})zgetting license requestzsession ID does not existr#   z+no client ID blob available for this deviceÚrbz%client id failed to parse as protobufzbuilding license requestZLICENSE_REQUESTZOFFLINEÚDEFAULTZNEWZCURRENTé   é   z!vmp required, adding to client_idzreading vmp hashesz&vmp hashes failed to parse as protobufz?privacy mode & service certificate loaded, encrypting client idzunencrypted client id:r!   z4need device private key, other methods unimplementedzsigning license requestzlicense request:zlicense request createdzlicense request b64: {}l        )Rr   r$   r%   r&   r   r*   r.   r7   ZSignedLicenseRequestRawZSignedLicenseRequestZClientIdentificationÚosÚpathÚexistsZdevice_configZdevice_client_id_blob_filenameÚopenr8   Úreadr   ZMessageTypeZValuer@   rA   Z	ContentIdZCencIdZPsshZCopyFromr4   r1   ZLicenseTypeZ	RequestIdZLicenseRequestZRequestTypeÚintÚtimeZRequestTimeZProtocolVersionZsend_key_control_noncer   Ú	randrangeZKeyControlNoncerC   ZvmpZ
FileHashesZdevice_vmp_blob_filenameZ_FileHashesr   r;   r<   r   r   ÚnewÚMODE_CBCZencryptr   ÚpadÚSerializeToStringr   Z	importKeyrB   Z_DeviceCertificateZ	PublicKeyr   ZEncryptedClientIdentificationZ	ServiceIdZSerialNumberZServiceCertificateSerialNumberZEncryptedClientIdZEncryptedClientIdIvZEncryptedPrivacyKeyZClientIdZprivate_key_availableZdevice_private_key_filenameÚ
device_keyr   r   ÚsignÚ	SignatureÚlicense_requestr9   Ú	b64encode)r   r3   rD   rZ   Z	client_idÚfZ	cid_bytesZlicense_typeZ
vmp_hashesZ	vmp_bytesr=   Zcid_aes_keyZcid_ivZ
cid_cipherZencrypted_client_idZservice_public_keyZservice_cipherZencrypted_cid_keyZencrypted_client_id_protoÚkeyÚhashÚ	signaturer   r   r   Úget_license_request„   s¤    







zCdm.get_license_requestc       $      C   sî  | j jdj||ƒƒ | j jdƒ || jkr:| j jdƒ dS | j| }|jsZ| j jdƒ dS tjƒ }y|j	t
j|ƒƒ W n  tk
r–   | j jdƒ dS X ||_| j jdƒ x"tj|ƒjƒ D ]}| j j|ƒ qºW | j jdƒ tj|jƒ}|j|jƒ|_|jjjƒ }d	| d
 }d| d }	d| }
d|	 }d|	 }d|	 }d|	 }tj|jtd�}|j|
ƒ |jƒ }tj|jtd�}|j|ƒ |jƒ }tj|jtd�}|j|ƒ |jƒ }tj|jtd�}|j|ƒ |jƒ }tj|jtd�}|j|ƒ |jƒ }|| }|| }||jd< ||jd< ||jd< | j jdƒ tj|jd td�}|j|jjƒ ƒ | j jdj|j ƒ t!j"|j#ƒƒƒ |jƒ |j#k�rÚ| j jdƒ t$ddƒ�}|j%t
j|ƒƒ W d Q R X t$ddƒ�}|j%|jƒ ƒ W d Q R X | j jdƒ | j jdjt&|jj'ƒƒƒ xè|jj'D ]Ü}|j(�r|j(}ntj)j*j+j,|j-ƒj.dƒ}|j'}|j/}tj)j*j+j,|j-ƒ}tj|jd tj0|d�}|j|ƒ}|d k�r¶g } |j1}!x,|!j2ƒ D ] \}"}#|#dk�rˆ| j3|"j4ƒ �qˆW t5| ƒ ng } |j6j3t'||t7j8|d!ƒ| ƒƒ �qþW | j jd"ƒ d#S )$Nz.provide_license(session_id={}, license_b64={})zdecrypting provided licensezsession does not existr#   z!generate a license request first!z)unable to parse license - check protobufszlicense:zderiving keys from session keys   ENCRYPTION s      €s   AUTHENTICATION s      ó   ó   ó   ó   )Z	ciphermodÚencZauth_1Zauth_2zverifying license signature)Ú	digestmodz!calculated sig: {} actual sig: {}zElicense signature doesn't match - writing bin so they can be debuggedzoriginal_lic.binÚwbzparsed_lic.binzcontinuing anywayzkey count: {}zutf-8)ÚivZOPERATOR_SESSIONr!   zdecrypted all keysr   )9r   r$   r%   r&   r   r*   rZ   r7   ZSignedLicenser8   r9   r:   r   Úlicenser   r;   r<   r   rS   rW   ÚdecryptZ
SessionKeyZsession_keyrA   rV   r   r   ÚupdateÚdigestZderived_keysr
   r	   Ú	hexdigestÚbinasciiÚhexlifyrY   rN   ÚwriteÚlenr   ZIdZLicenseZKeyContainerZKeyTypeÚNamer@   r)   ZIvrT   Z_OperatorSessionKeyPermissionsZ
ListFieldsÚappendÚnameÚprintÚkeysr   Zunpad)$r   r3   Úlicense_b64rD   ri   r=   Zoaep_cipherZlic_req_msgZenc_key_baseZauth_key_baseZenc_keyZ
auth_key_1Z
auth_key_2Z
auth_key_3Z
auth_key_4Zcmac_objZenc_cmac_keyZauth_cmac_key_1Zauth_cmac_key_2Zauth_cmac_key_3Zauth_cmac_key_4Zauth_cmac_combined_1Zauth_cmac_combined_2Zlic_hmacr\   r]   Zkey_idZencrypted_keyrh   ÚtypeÚcipherZdecrypted_keyZpermissionsZpermsZ
descriptorÚvaluer   r   r   Úprovide_licenseô   s¤    









 



$zCdm.provide_licensec             C   s*   || j kr| j | jS | jjdƒ dS d S )Nzsession not foundr#   )r   rv   r   r*   )r   r3   r   r   r   Úget_keyse  s    
zCdm.get_keys)NF)r   Ú
__module__Ú__qualname__r   r5   r/   r?   rF   r`   r{   r|   r   r   r   r   r      s   
"+pqr   )"r9   rK   rQ   rn   r   Zgoogle.protobuf.messager   Zgoogle.protobufr   ZCryptodome.Randomr   r   ZCryptodome.Cipherr   r   ZCryptodome.Hashr   r	   r
   r   ZCryptodome.PublicKeyr   ZCryptodome.Signaturer   ZCryptodome.Utilr   Zpywidevine.cdm.formatsr   r7   Zpywidevine.cdm.sessionr   Zpywidevine.cdm.keyr   r   r   r   r   r   Ú<module>   s"   