B
    QUc                 @   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
mZ d dlmZmZmZ d dlmZ G dd deZd	ZG d
d dZG dd dZdS )    N)utils)InvalidSignature)hashespadding)Cipher
algorithmsmodes)HMACc               @   s   e Zd ZdS )InvalidTokenN)__name__
__module____qualname__ r   r   2lib/python3.7/site-packages/cryptography/fernet.pyr
      s   r
   <   c               @   s*  e Zd Zd!ejeef ejdddZe	edddZ
eedd	d
ZeeedddZeeeedddZd"ejeef eje edddZejeef eeedddZejeef edddZeejeef ejeef dddZeddddZeeejejeef  eddd ZdS )#FernetN)keybackendc          
   C   sr   yt |}W n. tjk
r< } ztd|W d d }~X Y nX t|dkrRtd|d d | _|dd  | _d S )Nz4Fernet key must be 32 url-safe base64-encoded bytes.       )base64urlsafe_b64decodebinasciiError
ValueErrorlen_signing_key_encryption_key)selfr   r   excr   r   r   __init__   s    zFernet.__init__)returnc             C   s   t tdS )Nr   )r   urlsafe_b64encodeosurandom)clsr   r   r   generate_key.   s    zFernet.generate_key)datar!   c             C   s   |  |tt S )N)encrypt_at_timeinttime)r   r'   r   r   r   encrypt2   s    zFernet.encrypt)r'   current_timer!   c             C   s   t d}| |||S )Nr   )r#   r$   _encrypt_from_parts)r   r'   r,   ivr   r   r   r(   5   s    
zFernet.encrypt_at_time)r'   r,   r.   r!   c             C   s   t d| ttjj }|||	  }t
t| jt| }|||	  }d|jddd | | }t| jt }	|	| |		 }
t||
 S )Nr'         big)length	byteorder)r   _check_bytesr   PKCS7r   AES
block_sizepadderupdatefinalizer   r   r   CBC	encryptorto_bytesr	   r   r   SHA256r   r"   )r   r'   r,   r.   r8   Zpadded_datar<   
ciphertextZbasic_partshZhmacr   r   r   r-   9   s    

zFernet._encrypt_from_parts)tokenttlr!   c             C   s:   t |\}}|d krd }n|tt f}| |||S )N)r   _get_unverified_token_datar)   r*   _decrypt_data)r   rA   rB   	timestampr'   	time_infor   r   r   decryptR   s
    zFernet.decrypt)rA   rB   r,   r!   c             C   s0   |d krt dt|\}}| ||||fS )Nz6decrypt_at_time() can only be used with a non-None ttl)r   r   rC   rD   )r   rA   rB   r,   rE   r'   r   r   r   decrypt_at_time\   s
    zFernet.decrypt_at_time)rA   r!   c             C   s   t |\}}| | |S )N)r   rC   _verify_signature)r   rA   rE   r'   r   r   r   extract_timestampf   s    
zFernet.extract_timestampc          	   C   s   t | ttfstdyt| }W n ttjfk
rB   tY nX |rT|d dkrXtt	|dk rhtt
j|dd dd}||fS )Nztoken must be bytes or strr      	      r1   )r3   )
isinstancestrbytes	TypeErrorr   r   r   r   r
   r   r)   
from_bytes)rA   r'   rE   r   r   r   rC   l   s    
z!Fernet._get_unverified_token_datac             C   sV   t | jt }||d d  y||dd   W n tk
rP   tY nX d S )Ni)r	   r   r   r>   r9   Zverifyr   r
   )r   r'   r@   r   r   r   rI      s    zFernet._verify_signature)r'   rE   rF   r!   c             C   s   |d k	r0|\}}|| |k r t |t |k r0t | | |dd }|dd }tt| jt|	 }|
|}	y|	| 7 }	W n tk
r   t Y nX ttjj }
|

|	}y||
 7 }W n tk
r   t Y nX |S )NrL      i)r
   _MAX_CLOCK_SKEWrI   r   r   r6   r   r   r;   	decryptorr9   r:   r   r   r5   r7   unpadder)r   r'   rE   rF   rB   r,   r.   r?   rU   Zplaintext_paddedrV   Zunpaddedr   r   r   rD      s.    




zFernet._decrypt_data)N)N)r   r   r   typingUnionrP   rO   ZAnyr    classmethodr&   r+   r)   r(   r-   OptionalrG   rH   rJ   staticmethodZTuplerC   rI   rD   r   r   r   r   r      s(   	
r   c               @   s   e Zd Zeje dddZeedddZee	eddd	Z
ejeef edd
dZdejeef eje	 edddZejeef e	e	edddZdS )MultiFernet)fernetsc             C   s   t |}|std|| _d S )Nz1MultiFernet requires at least one Fernet instance)listr   _fernets)r   r]   r   r   r   r       s
    zMultiFernet.__init__)msgr!   c             C   s   |  |tt S )N)r(   r)   r*   )r   r`   r   r   r   r+      s    zMultiFernet.encrypt)r`   r,   r!   c             C   s   | j d ||S )Nr   )r_   r(   )r   r`   r,   r   r   r   r(      s    zMultiFernet.encrypt_at_timec          	   C   sj   t |\}}x<| jD ].}y|||d }P W q tk
rB   Y qX qW ttd}| jd |||S )Nr   r   )r   rC   r_   rD   r
   r#   r$   r-   )r   r`   rE   r'   fpr.   r   r   r   rotate   s    

zMultiFernet.rotateN)r`   rB   r!   c          	   C   s:   x0| j D ]&}y|||S  tk
r,   Y qX qW td S )N)r_   rG   r
   )r   r`   rB   ra   r   r   r   rG      s    
zMultiFernet.decrypt)r`   rB   r,   r!   c          	   C   s<   x2| j D ](}y||||S  tk
r.   Y qX qW td S )N)r_   rH   r
   )r   r`   rB   r,   ra   r   r   r   rH      s    
zMultiFernet.decrypt_at_time)N)r   r   r   rW   Iterabler   r    rP   r+   r)   r(   rX   rO   rc   rZ   rG   rH   r   r   r   r   r\      s   	r\   )r   r   r#   r*   rW   Zcryptographyr   Zcryptography.exceptionsr   Zcryptography.hazmat.primitivesr   r   Z&cryptography.hazmat.primitives.ciphersr   r   r   Z#cryptography.hazmat.primitives.hmacr	   	Exceptionr
   rT   r   r\   r   r   r   r   <module>   s    