U
    h                     @   s   d Z ddlZddlZddlmZ ddlmZmZmZm	Z	m
Z
mZmZmZmZ ddl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mZmZ dd ZdddZdS )z
This module contains several functions that authenticate the client machine
with Telegram's servers, effectively creating an authorization key.
    N)sha1   )	ResPQPQInnerDataServerDHParamsFailServerDHParamsOkServerDHInnerDataClientDHInnerDataDhGenOk
DhGenRetry	DhGenFail)helpers)AESAuthKeyFactorizationrsa)SecurityError)BinaryReader)ReqPqMultiRequestReqDHParamsRequestSetClientDHParamsRequestc           $   
      s  t jtdddd}| t|I dH }t|ts@td| |j	|krRt
dt|j}t|\}}t|t| }}t jtdd	dd}ttt||||j	|j|d
}d\}}	|jD ] }
t|
|}|dk	r|
}	 qq|dkr |jD ]&}
tj|
|dd}|dk	r|
}	 q q|dkrJt
dddd |jD | t|j	|j|||	|dI dH }t|ttfstd| |j	|j	krt
d|j|jkrt
dt|trt jt|jdd	dd dd d	dd}|j|krt
dt|tstd| t |j|\}}t!|j"d dkrHt
dt#$|j"||}t%|0}|&d |' }t|t(std| W 5 Q R X |j	|j	krt
d|j|jkrt
dt|j)dd}|j*}t|j+dd}|j,t t--  }ttddd}t.|||}t.|||}d |  k r<|d  k sFn t
d!d |  k rb|d  k sln t
d!d |  k r|d  k sn t
d"d#d$ }||  kr|| ksn t
d%||  kr|| ksn t
d&tt/|j	|jdt|d'}t| | }t#0|||}| t1|j	|j|d(I dH }t2t3t4f}t||sbtd)| |j5j6}|j	|j	krt
d*||j|jkrt
d+|t7t|} d |8t9| }!| :||!}"t;|d,|!}#|#|"krt
d-t|t2std.| | |fS )/z
    Executes the authentication process with the Telegram servers.

    :param sender: a connected `MTProtoPlainSender`.
    :return: returns a (authorization key, time offset) tuple.
       bigT)signedNzStep 1 answer was %sz Step 1 invalid nonce from server    little)pqpqnonceserver_nonce	new_nonce)NN)Zuse_oldz6Step 2 could not find a valid key for fingerprints: {}z, c                 S   s   g | ]}t |qS  )str).0fr"   r"   B/tmp/pip-unpacked-wheel-c81u5j2r/telethon/network/authenticator.py
<listcomp>G   s     z%do_authentication.<locals>.<listcomp>)r   r    r   r   Zpublic_key_fingerprintencrypted_datazStep 2.1 answer was %sz Step 2 invalid nonce from serverz'Step 2 invalid server nonce from server      z(Step 2 invalid DH fail nonce from serverzStep 2.2 answer was %sr   zStep 3 AES block size mismatchzStep 3 answer was %sz(Step 3 Invalid nonce in encrypted answerz/Step 3 Invalid server nonce in encrypted answerF      z#g_a is not within (1, dh_prime - 1)z#g_b is not within (1, dh_prime - 1)r   i  z7g_a is not within (2^{2048-64}, dh_prime - 2^{2048-64})z7g_b is not within (2^{2048-64}, dh_prime - 2^{2048-64}))r   r    Zretry_idg_b)r   r    r(   zStep 3.1 answer was %sz#Step 3 invalid {} nonce from serverz*Step 3 invalid {} server nonce from serverznew_nonce_hash{}zStep 3 invalid new nonce hashzStep 3.2 answer was %s)<int
from_bytesosurandomsendr   
isinstancer   AssertionErrorr   r   get_intr   r   Z	factorizer   Zget_byte_arraybytesr   r    Zserver_public_key_fingerprintsZencryptformatjoinr   r   r   r   to_bytesdigestnew_nonce_hashr   Zgenerate_key_data_from_noncelenZencrypted_answerr   Zdecrypt_iger   readZtgread_objectr   dh_primegg_aZserver_timetimepowr	   Zencrypt_iger   r
   r   r   	__class____name__r   indextypeZcalc_new_nonce_hashgetattr)$Zsenderr   Zres_pqr   r   r   r!   Zpq_inner_dataZcipher_textZtarget_fingerprintfingerprintZserver_dh_paramsZnnhkeyZivZplain_text_answerreaderZserver_dh_innerr>   r?   r@   Ztime_offsetbr-   ZgabZsafety_rangeZclient_dh_innerZclient_dh_inner_hashedZclient_dh_encryptedZdh_genZnonce_typesnameZauth_keyZnonce_numberr;   Zdh_hashr"   r"   r&   do_authentication   s   

  



      



rM   Tc                 C   s   t j| d|dS )a8  
    Gets the specified integer from its byte array.
    This should be used by this module alone, as it works with big endian.

    :param byte_array: the byte array representing th integer.
    :param signed: whether the number is signed or not.
    :return: the integer representing the given byte array.
    r   )	byteorderr   )r.   r/   )Z
byte_arrayr   r"   r"   r&   r5      s    	r5   )T) __doc__r0   rA   hashlibr   Ztl.typesr   r   r   r   r   r	   r
   r   r    r   Zcryptor   r   r   r   errorsr   
extensionsr   Ztl.functionsr   r   r   rM   r5   r"   r"   r"   r&   <module>   s   , 6