U
    T	a                     @   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m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 ed	ZG d
d deZG dd deZdd Zdd Zd$ddZd%ddZG dd dZddedfddZddedfddZG d d! d!ZG d"d# d#eZdS )&ae  
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/SHA1 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-ze3TTx7gtSv422nZA4sgmk-modified")
...
BadSignature: Signature failed: ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv422nZA4sgmk-modified

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)baseconv)constant_time_comparesalted_hmac)force_bytes)import_string)_lazy_re_compilez^[A-z0-9-_=]*$c                   @   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-swgtpe36/django/core/signing.pyr	   4   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   9   s   r   c                 C   s   t | dS )N   =)base64urlsafe_b64encodestrip)sr   r   r   
b64_encode>   s    r   c                 C   s    dt |  d  }t| | S )Nr      )lenr   urlsafe_b64decode)r   padr   r   r   
b64_decodeB   s    r   sha1c                 C   s   t t| |||d  S )N	algorithm)r   r   digestdecode)saltvaluekeyr   r   r   r   base64_hmacG   s    r%   %django.core.signing.get_cookie_signerc                 C   s$   t tj}ttj}|d| | dS )Ns   django.http.cookiesr"   )r   r   ZSIGNING_BACKENDr   
SECRET_KEY)r"   Signerr$   r   r   r   get_cookie_signerK   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   r1   V   s    zJSONSerializer.dumpsc                 C   s   t |dS )Nr/   )r0   loadsr!   )r3   datar   r   r   r5   Y   s    zJSONSerializer.loadsN)r   r   r   r   r1   r5   r   r   r   r   r+   Q   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.
    r'   )
serializercompress)TimestampSignersign_object)r4   r$   r"   r7   r8   r   r   r   r1   ]   s    r1   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.
    r'   )r7   max_age)r9   unsign_object)r   r$   r"   r7   r;   r   r   r   r5   q   s    r5   c                   @   sT   e Zd ZdZdddZdd Zdd	 Zd
d Zdd Ze	dfddZ
e	fddZdS )r)   r   Nr-   c                 C   sT   |pt j| _|| _t| jr*td| |p@d| jj| jj	f | _
|pLt j| _d S )NzJUnsafe Signer separator: %r (cannot be empty or consist of only A-z0-9-_=)z%s.%s)r   r(   r$   sep_SEP_UNSAFEmatch
ValueError	__class__r   r   r"   ZDEFAULT_HASHING_ALGORITHMr   )r3   r$   r=   r"   r   r   r   r   __init__~   s    zSigner.__init__c                 C   s   t | jd || j| jdS NZsignerr   )r%   r"   r$   r   r3   r#   r   r   r   	signature   s    zSigner.signaturec                 C   s   t | jd || j| jdS rC   )r%   r"   r$   legacy_algorithmrD   r   r   r   _legacy_signature   s    zSigner._legacy_signaturec                 C   s   d|| j | |f S Nz%s%s%s)r=   rE   rD   r   r   r   sign   s    zSigner.signc                 C   sd   | j |krtd| j  || j d\}}t|| |sP| jrTt|| |rT|S td| d S )NzNo "%s" found in value   zSignature "%s" does not match)r=   r	   rsplitr   rE   rF   rG   )r3   Zsigned_valuer#   sigr   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.
        FrJ   T.)r1   zlibr8   r   r   r!   rI   )r3   r4   r7   r8   r6   Zis_compressed
compressedbase64dr   r   r   r:      s    

zSigner.sign_objectc                 K   sT   | j |f| }|d d dk}|r2|dd  }t|}|rHt|}| |S )NrJ      .)rM   r2   r   rO   
decompressr5   )r3   Z
signed_objr7   kwargsrQ   rS   r6   r   r   r   r<      s    
zSigner.unsign_object)Nr-   NN)r   r   r   rF   rB   rE   rG   rI   rM   r+   r:   r<   r   r   r   r   r)   z   s   
r)   c                       s2   e Zd Zdd Z fddZd fdd	Z  ZS )	r9   c                 C   s   t jtt S )N)r   base62r2   inttime)r3   r   r   r   	timestamp   s    zTimestampSigner.timestampc                    s    d|| j |  f }t |S rH   )r=   rX   superrI   rD   rA   r   r   rI      s    zTimestampSigner.signNc                    sn   t  |}|| jd\}}tj|}|dk	rjt|tj	rF|
 }t | }||krjtd||f |S )zk
        Retrieve original value and check it wasn't signed more
        than max_age seconds ago.
        rJ   NzSignature age %s > %s seconds)rY   rM   rK   r=   r   rU   r!   
isinstancedatetime	timedeltatotal_secondsrW   r   )r3   r#   r;   resultrX   ZagerZ   r   r   rM      s    
zTimestampSigner.unsign)N)r   r   r   rX   rI   rM   __classcell__r   r   rZ   r   r9      s   r9   )r   )r&   ) r   r   r\   r0   rW   rO   Zdjango.confr   Zdjango.utilsr   Zdjango.utils.cryptor   r   Zdjango.utils.encodingr   Zdjango.utils.module_loadingr   Zdjango.utils.regex_helperr   r>   	Exceptionr	   r   r   r   r%   r*   r+   r1   r5   r)   r9   r   r   r   r   <module>   s.   #

	O