o
    ӷ6i                     @   s   d dl Z d dlZd dlmZ d dlmZmZmZ d dl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 e ZG dd deZdddZejZdd ZdddZG dd dZG dd deZdS )    N)Error)constant_timehashespadding)Cipher
algorithmsmodes)HMAC)
PBKDF2HMAC)crypto)force_bytes   )CryptographyConfc                   @   s   e Zd ZdS )InvalidTokenN)__name__
__module____qualname__ r   r   e/var/www/hoanhtaovolam_webdjango/env/lib/python3.10/site-packages/django_cryptography/utils/crypto.pyr      s    r   c                 C   sj   |du rt j}t| } t|}tjt jt jd}|| |  | }t	|t jt jd}|t| |S )a+  
    Returns the HMAC-HASH of 'value', using a key generated from key_salt and a
    secret (which defaults to settings.SECRET_KEY).

    A different key_salt should be passed in for every application of HMAC.

    :type key_salt: any
    :type value: any
    :type secret: any
    :rtype: HMAC
    N)backend)
settings
SECRET_KEYr   r   HashCRYPTOGRAPHY_DIGESTCRYPTOGRAPHY_BACKENDupdatefinalizer	   )key_saltvaluesecretdigestkeyhr   r   r   salted_hmac   s   r#   c                 C   s   t t| t|S )z>
    :type val1: any
    :type val2: any
    :rtype: bool
    )r   bytes_eqr   )val1val2r   r   r   constant_time_compare<   s   r'   c                 C   sF   |du rt j}|s|j}t| } t|}t||||t jd}|| S )a  
    Implements PBKDF2 with the same API as Django's existing
    implementation, using cryptography.

    :type password: any
    :type salt: any
    :type iterations: int
    :type dklen: int
    :type digest: cryptography.hazmat.primitives.hashes.HashAlgorithm
    N)	algorithmlengthsalt
iterationsr   )r   r   digest_sizer   r
   r   derive)passwordr*   r+   dklenr    kdfr   r   r   pbkdf2E   s   
r1   c                   @   s4   e Zd ZdZdddZdd Zdd Zdd	d
ZdS )FernetBytesa$  
    This is a modified version of the Fernet encryption algorithm from
    the Python Cryptography library. The main change is the allowance
    of varied length cryptographic keys from the base 128-bit. There is
    also an emphasis on using Django's settings system for sane defaults.
    Nc                 C   s8   |d u rddl m} | }tj| _|ptj| _|| _d S )Nr   FernetSigner)core.signingr4   r   r   _backendCRYPTOGRAPHY_KEY_encryption_key_signer)selfr!   signerr4   r   r   r   __init__h   s   
zFernetBytes.__init__c                 C   s   t |}td}| ||S )z5
        :type data: any
        :rtype: any
           )r   osurandom_encrypt_from_parts)r:   dataivr   r   r   encryptq   s   
zFernetBytes.encryptc                 C   sf   t tjj }|||  }tt| j	t
|| j }|||  }| j|| S )zO
        :type data: bytes
        :type iv: bytes
        :rtype: any
        )r   PKCS7r   AES
block_sizepadderr   r   r   r8   r   CBCr6   	encryptorr9   sign)r:   rA   rB   rG   padded_datarI   
ciphertextr   r   r   r@   z   s   zFernetBytes._encrypt_from_partsc           	      C   s   | j ||}|dd }|dd }tt| jt|| j	 }|
|}z|| 7 }W n	 ty9   tw ttjj }|
|}z	|| 7 }W |S  tyZ   tw )zP
        :type data: bytes
        :type ttl: int
        :rtype: bytes
        Nr=   )r9   unsignr   r   rE   r8   r   rH   r6   	decryptorr   r   
ValueErrorr   r   rD   rF   unpadder)	r:   rA   ttlrB   rL   rN   plaintext_paddedrP   unpaddedr   r   r   decrypt   s,   

zFernetBytes.decrypt)NNN)r   r   r   __doc__r<   rC   r@   rT   r   r   r   r   r2   `   s    
		r2   c                       s6   e Zd Z fddZ fddZd fdd	Z  ZS )	Fernetc                    sP   t |}t|dkrtdddlm} t |dd  ||d d  d S )N    z4Fernet key must be 32 url-safe base64-encoded bytes.r   r3   r=   )base64urlsafe_b64decodelenrO   r5   r4   superr<   )r:   r!   r4   	__class__r   r   r<      s
   
&zFernet.__init__c                    s   t  ||}t|S rU   )r\   r@   rY   urlsafe_b64encode)r:   rA   rB   payloadr]   r   r   r@      s   
zFernet._encrypt_from_partsNc              	      s4   zt |}W n ttfy   tw t ||S rU   )rY   rZ   	TypeErrorr   r   r\   rT   )r:   tokenrQ   rA   r]   r   r   rT      s   zFernet.decryptrU   )r   r   r   r<   r@   rT   __classcell__r   r   r]   r   rW      s    rW   rU   )r   N)rY   r>   binasciir   cryptography.hazmat.primitivesr   r   r   &cryptography.hazmat.primitives.ciphersr   r   r   #cryptography.hazmat.primitives.hmacr	   )cryptography.hazmat.primitives.kdf.pbkdf2r
   django.utilsr   django.utils.encodingr   confr   r   	Exceptionr   r#   get_random_stringr'   r1   r2   rW   r   r   r   r   <module>   s$    
$
	F