3
uQh                 @   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jdddd}| jt|I dH }t|ts@td| |j	|krRt
dt|j}tj|\}}tj|tj| }}t jtjdd	dd}tttj||||j	|j|d
}d/\}}	x(|jD ]}
tj|
|}|dk	r|
}	P qW |dkr&x0|jD ]&}
tj|
|dd}|dk	 r|
}	P  qW |dkrPt
djdjdd |jD | j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j dd d	dd}|j|krt
dt|ts td| tj |j|\}}t!|j"d dkrNt
dt#j$|j"||}t%|0}|j&d |j' }t|t(std| W d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-j-  }ttjddd}t.|||}t.|||}d|  k o>|d k n  sNt
d d|  k of|d k n  svt
d d|  k o|d k n  st
d!d"d0 }||  ko|| kn  st
d%||  ko|| kn  st
d&tt/|j	|jdtj|d'}t|j | }t#j0|||}| jt1|j	|j|d(I dH }t2t3t4f}t||srtd)| |j5j6}|j	|j	krt
d*j||j|jkrt
d+j|t7tj|} d|j8t9| }!| j:||!}"t;|d,j|!}#|#|"kr t
d-t|t2std.| | |fS )1z
    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)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-build-2nz6shyl/telethon/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)NNi  )<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@   rA   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    










     

rN   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/   r0   )Z
byte_arrayr   r"   r"   r&   r6      s    	r6   )T) __doc__r1   rB   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   rN   r6   r"   r"   r"   r&   <module>   s   , 6