U
    Ýëdç  ã                   @   sâ   d Z ddlmZ z0ddlmZ ddlmZmZ ddlm	Z	 dZ
W n ek
rX   dZ
Y nX dd	lmZ dd
lZdZdZeejdƒZdd„ Zdd„ Zdadd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd „ Zd!d"„ Zd
S )#z
Implements auth methods
é   )ÚOperationalErroré    )Údefault_backend)ÚserializationÚhashes)ÚpaddingTF)ÚpartialNé   Úsha1c                 C   sT   | sdS t | ƒ ¡ }t |ƒ ¡ }t ƒ }| |dt… ¡ | |¡ | ¡ }t||ƒS )z'Scramble used for mysql_native_passwordó    N)Úsha1_newÚdigestÚupdateÚSCRAMBLE_LENGTHÚ	_my_crypt)ÚpasswordÚmessageZstage1Zstage2ÚsÚresult© r   ú1/tmp/pip-unpacked-wheel-zrp_b4p0/pymysql/_auth.pyÚscramble_native_password   s    
r   c                 C   s6   t | ƒ}tt|ƒƒD ]}||  || N  < qt|ƒS ©N)Ú	bytearrayÚrangeÚlenÚbytes)Zmessage1Zmessage2r   Úir   r   r   r   +   s    r   c                  C   s6   zddl m}  | aW n tk
r0   tdƒ‚Y nX d S )Nr   ©Úbindingsz='pynacl' package is required for ed25519_password auth method)Znaclr   Ú_nacl_bindingsÚImportErrorÚRuntimeErrorr   r   r   r   Ú
_init_nacl:   s    ÿr#   c                 C   sP   t | ƒ}tt |d d@ gƒƒ}tt |d d@ dB gƒƒ}|t| dd… ƒ | S )Nr   éø   é   é   é@   r   )r   r   )Zs32ÚbaZba0Zba31r   r   r   Ú_scalar_clampF   s    r)   c           
      C   s    t s
tƒ  t | ¡ ¡ }t|dd… ƒ}t |dd… | ¡ ¡ }t  |¡}t  |¡}t  |¡}t || | ¡ ¡ }t  |¡}t  ||¡}t  	||¡}	||	 S )znSign a random scramble with elliptic curve Ed25519.

    Secret and public key are derived from password.
    Né    )
r    r#   ÚhashlibÚsha512r   r)   Z!crypto_core_ed25519_scalar_reduceZ&crypto_scalarmult_ed25519_base_noclampZcrypto_core_ed25519_scalar_mulZcrypto_core_ed25519_scalar_add)
r   ZscrambleÚhr   ÚrÚRÚAÚkÚksÚSr   r   r   Úed25519_passwordM   s    



r4   c                 C   s   |   |¡ |  ¡ }| ¡  |S r   )Zwrite_packetÚ_read_packetÚcheck_error)ÚconnZ	send_dataÚpktr   r   r   Ú
_roundtripv   s    
r9   c                 C   sN   |d t … }t| ƒ}t|ƒ}tt|ƒƒD ]}||  |||  N  < q(t|ƒS r   )r   r   r   r   r   )r   ÚsaltZpassword_bytesZsalt_lenr   r   r   r   Ú_xor_password}   s    r;   c                 C   sP   t stdƒ‚t| d |ƒ}t |tƒ ¡}| |tjtj	t
 ¡ dt
 ¡ dd¡S )zhEncrypt password with salt and public_key.

    Used for sha256_password and caching_sha2_password.
    z\'cryptography' package is required for sha256_password or caching_sha2_password auth methodsó    )Ú	algorithmN)Zmgfr=   Úlabel)Ú_have_cryptographyr"   r;   r   Zload_pem_public_keyr   Zencryptr   ZOAEPZMGF1r   ÚSHA1)r   r:   Z
public_keyr   Zrsa_keyr   r   r   Úsha2_rsa_encrypt‰   s    ÿýþrA   c                 C   s¾   | j r&trtdƒ | jd }t| |ƒS | ¡ rZ| ¡ | _| jsZ| jrZtrPtdƒ t| dƒ}| 	¡ rˆ|j
dd … | _trˆtd| j d¡ƒ | jr°| jsœtdƒ‚t| j| j| jƒ}nd	}t| |ƒS )
Nzsha256: Sending plain passwordr<   z$sha256: Requesting server public keyó   r   zReceived public key:
Úasciiz$Couldn't receive server's public keyr   )Ú_secureÚDEBUGÚprintr   r9   Úis_auth_switch_requestÚread_allr:   Úserver_public_keyÚis_extra_auth_dataÚ_dataÚdecoder   rA   )r7   r8   Údatar   r   r   Úsha256_password_authž   s*    



rN   c                 C   sl   | sdS t  | ¡ ¡ }t  |¡ ¡ }t  || ¡ ¡ }t|ƒ}tt|ƒƒD ]}||  || N  < qJt|ƒS )zƒScramble algorithm used in cached_sha2_password fast path.

    XOR(SHA256(password), SHA256(SHA256(SHA256(password)), nonce))
    r   )r+   Úsha256r   r   r   r   r   )r   ÚnonceÚp1Úp2Zp3Úresr   r   r   r   Úscramble_caching_sha2½   s    rT   c                 C   sX  | j st| dƒS | ¡ rFtr$tdƒ | ¡ | _t| j | jƒ}t| |ƒ}| ¡ sdt	d|j
d d…  ƒ‚| d¡ | ¡ }|dkržtrŠtdƒ |  ¡ }| ¡  |S |dkr²t	d| ƒ‚tr¾td	ƒ | jràtrÐtd
ƒ t| | j d ƒS | js8t| dƒ}| ¡ st	d|j
d d…  ƒ‚|j
dd … | _tr8t| j d¡ƒ t| j | j| jƒ}t| |ƒ}d S )Nr   zcaching sha2: Trying fast pathz.caching sha2: Unknown packet for fast auth: %sr   é   z%caching sha2: succeeded by fast path.é   z.caching sha2: Unknwon result for fast auth: %sz!caching sha2: Trying full auth...z:caching sha2: Sending plain password via secure connectionr<   ó   z/caching sha2: Unknown packet for public key: %srC   )r   r9   rG   rE   rF   rH   r:   rT   rJ   r   rK   ZadvanceZ
read_uint8r5   r6   rD   rI   rL   rA   )r7   r8   Z	scrambledÚnrM   r   r   r   Úcaching_sha2_password_authÑ   sN    


ÿ	


ÿrY   )Ú__doc__Úerrr   Zcryptography.hazmat.backendsr   Zcryptography.hazmat.primitivesr   r   Z)cryptography.hazmat.primitives.asymmetricr   r?   r!   Ú	functoolsr   r+   rE   r   Únewr   r   r   r    r#   r)   r4   r9   r;   rA   rN   rT   rY   r   r   r   r   Ú<module>   s2   
)