U
    Z8wdh%                     @   s>  d Z ddlZ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
mZ ddlmZ ddlmZ ddlmZ ddlmZ ed	Zd
ZG dd deZG dd deZdd Zdd Zdd Zdd Zd+ddZdd Zd,ddZG dd  d Z dd!e d"fd#d$Z!dd!e ddfd%d&Z"G d'd( d(Z#G d)d* d*e#Z$dS )-a_  
Functions for creating and restoring url-safe signed JSON objects.

The format used looks like this:

>>> signing.dumps("hello")
'ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv422nZA4sgmk'

There are two components here, separated by a ':'. The first component is a
URLsafe base64 encoded JSON of the object passed to dumps(). The second
component is a base64 encoded hmac/SHA-256 hash of "$first_component:$secret"

signing.loads(s) checks the signature and returns the deserialized object.
If the signature fails, a BadSignature exception is raised.

>>> signing.loads("ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv422nZA4sgmk")
'hello'
>>> signing.loads("ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv42-modified")
...
BadSignature: Signature "ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv42-modified" does not match

You can optionally compress the JSON prior to base64 encoding it to save
space, using the compress=True argument. This checks if compression actually
helps and only applies compression if the result is a shorter string:

>>> signing.dumps(list(range(1, 20)), compress=True)
'.eJwFwcERACAIwLCF-rCiILN47r-GyZVJsNgkxaFxoDgxcOHGxMKD_T7vhAml:1QaUaL:BA0thEZrp4FQVXIXuOvYJtLJSrQ'

The fact that the string is compressed is signalled by the prefixed '.' at the
start of the base64 JSON.

There are 65 url-safe characters: the 64 used by url-safe base64 and the ':'.
These functions make use of all of them.
    N)settings)constant_time_comparesalted_hmac)RemovedInDjango51Warningforce_bytes)import_string)_lazy_re_compilez^[A-z0-9-_=]*$Z>0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzc                   @   s   e Zd ZdZdS )BadSignaturezSignature does not match.N__name__
__module____qualname____doc__ r   r   7/tmp/pip-unpacked-wheel-d24squcy/django/core/signing.pyr
   6   s   r
   c                   @   s   e Zd ZdZdS )SignatureExpiredz3Signature timestamp is older than required max_age.Nr   r   r   r   r   r   <   s   r   c                 C   sT   | dkrdS | dk rdnd}t | } d}| dkrLt| d\} }t| | }q(|| S )Nr   0- >   )absdivmodBASE62_ALPHABET)ssignencoded	remainderr   r   r   
b62_encodeB   s    r   c                 C   sT   | dkrdS d}| d dkr,| dd  } d}d}| D ]}|d t | }q4|| S )Nr   r      r   r   )r   index)r   r   decodeddigitr   r   r   
b62_decodeN   s    r$   c                 C   s   t | dS )N   =)base64urlsafe_b64encodestrip)r   r   r   r   
b64_encode[   s    r)   c                 C   s    dt |  d  }t| | S )Nr%      )lenr&   urlsafe_b64decode)r   padr   r   r   
b64_decode_   s    r.   sha1c                 C   s   t t| |||d  S )N	algorithm)r)   r   digestdecode)saltvaluekeyr1   r   r   r   base64_hmacd   s    r7   c                 C   s   dt |  S )Ns   django.http.cookiesr   )r6   r   r   r   _cookie_signer_keyj   s    r8   %django.core.signing.get_cookie_signerc                 C   s&   t tj}|ttjtttj| dS )N)r6   fallback_keysr4   )r   r   ZSIGNING_BACKENDr8   
SECRET_KEYmapSECRET_KEY_FALLBACKS)r4   Signerr   r   r   get_cookie_signero   s    

r?   c                   @   s    e Zd ZdZdd Zdd ZdS )JSONSerializerzW
    Simple wrapper around json to be used in signing.dumps and
    signing.loads.
    c                 C   s   t j|dddS )N),:)
separatorslatin-1)jsondumpsencode)selfobjr   r   r   rF   ~   s    zJSONSerializer.dumpsc                 C   s   t |dS )NrD   )rE   loadsr3   )rH   datar   r   r   rJ      s    zJSONSerializer.loadsN)r   r   r   r   rF   rJ   r   r   r   r   r@   x   s   r@   zdjango.core.signingFc                 C   s   t ||dj| ||dS )a  
    Return URL-safe, hmac signed base64 compressed JSON string. If key is
    None, use settings.SECRET_KEY instead. The hmac algorithm is the default
    Signer algorithm.

    If compress is True (not the default), check if compressing using zlib can
    save some space. Prepend a '.' to signify compression. This is included
    in the signature, to protect against zip bombs.

    Salt can be used to namespace the hash, so that a signed string is
    only valid for a given namespace. Leaving this at the default
    value or re-using a salt value across different parts of your
    application without good cause is a security risk.

    The serializer is expected to return a bytestring.
    )r6   r4   )
serializercompress)TimestampSignersign_object)rI   r6   r4   rL   rM   r   r   r   rF      s
      rF   c                 C   s   t |||dj| ||dS )z|
    Reverse of dumps(), raise BadSignature if signature fails.

    The serializer is expected to accept a bytestring.
    )r6   r4   r:   )rL   max_age)rN   unsign_object)r   r6   r4   rL   rP   r:   r   r   r   rJ      s      rJ   c                   @   sV   e Zd ZddddddddZdddZdd	 Zd
d ZedfddZefddZ	dS )r>   NrB   )r6   sepr4   r1   r:   c          	      G   s   |pt j| _|d k	r|nt j| _|| _|p<d| jj| jjf | _	|pFd| _
|rtjd| jj dtdd t|ddd	d
dgD ] \}}|s|dkr~t| || q~t| jrtd| d S )Nz%s.%ssha256z Passing positional arguments to z is deprecated.   )
stacklevelr6   rR   r4   r1   r:   zJUnsafe Signer separator: %r (cannot be empty or consist of only A-z0-9-_=))r   r;   r6   r=   r:   rR   	__class__r   r   r4   r1   warningswarnr   zipsetattr_SEP_UNSAFEmatch
ValueError)	rH   r6   rR   r4   r1   r:   argsargattrr   r   r   __init__   s:    	
 zSigner.__init__c                 C   s"   |p| j }t| jd ||| jdS )NZsignerr0   )r6   r7   r4   r1   )rH   r5   r6   r   r   r   	signature   s    
zSigner.signaturec                 C   s   d|| j | |f S Nz%s%s%s)rR   rb   rH   r5   r   r   r   r      s    zSigner.signc                 C   sh   | j |krtd| j  || j d\}}| jf| jD ]}t|| ||r8|  S q8td| d S )NzNo "%s" found in valuer   zSignature "%s" does not match)rR   r
   rsplitr6   r:   r   rb   )rH   Zsigned_valuer5   sigr6   r   r   r   unsign   s    

zSigner.unsignFc                 C   s\   |  |}d}|r:t|}t|t|d k r:|}d}t| }|rRd| }| |S )ae  
        Return URL-safe, hmac signed base64 compressed JSON string.

        If compress is True (not the default), check if compressing using zlib
        can save some space. Prepend a '.' to signify compression. This is
        included in the signature, to protect against zip bombs.

        The serializer is expected to return a bytestring.
        Fr   T.)rF   zlibrM   r+   r)   r3   r   )rH   rI   rL   rM   rK   Zis_compressed
compressedbase64dr   r   r   rO      s    

zSigner.sign_objectc                 K   sT   | j |f| }|d d dk}|r2|dd  }t|}|rHt|}| |S )Nr      .)rg   rG   r.   ri   
decompressrJ   )rH   Z
signed_objrL   kwargsrk   rm   rK   r   r   r   rQ   	  s    
zSigner.unsign_object)N)
r   r   r   ra   rb   r   rg   r@   rO   rQ   r   r   r   r   r>      s   (
	r>   c                       s2   e Zd Zdd Z fddZd fdd	Z  ZS )	rN   c                 C   s   t tt S )N)r   inttime)rH   r   r   r   	timestamp  s    zTimestampSigner.timestampc                    s    d|| j |  f }t |S rc   )rR   rq   superr   rd   rV   r   r   r     s    zTimestampSigner.signNc                    sj   t  |}|| jd\}}t|}|dk	rft|tjrB| }t		 | }||krft
d||f |S )zk
        Retrieve original value and check it wasn't signed more
        than max_age seconds ago.
        r   NzSignature age %s > %s seconds)rr   rg   re   rR   r$   
isinstancedatetime	timedeltatotal_secondsrp   r   )rH   r5   rP   resultrq   Zagers   r   r   rg     s    zTimestampSigner.unsign)N)r   r   r   rq   r   rg   __classcell__r   r   rs   r   rN     s   rN   )r/   )r9   )%r   r&   ru   rE   rp   rW   ri   Zdjango.confr   Zdjango.utils.cryptor   r   Zdjango.utils.deprecationr   Zdjango.utils.encodingr   Zdjango.utils.module_loadingr   Zdjango.utils.regex_helperr	   r[   r   	Exceptionr
   r   r   r$   r)   r.   r7   r8   r?   r@   rF   rJ   r>   rN   r   r   r   r   <module>   sJ   #

	   

d