3
[                 @   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
 ddlmZmZ ddlmZ ddlmZ ej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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 )#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/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(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_stringz^[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-install-j7i95hgp/django/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.N)r	   r
   r   r   r   r   r   r   r   9   s   r   c             C   s   t j| jdS )N   =)base64urlsafe_b64encodestrip)sr   r   r   
b64_encode>   s    r   c             C   s    dt |  d  }tj| | S )Nr      )lenr   urlsafe_b64decode)r   padr   r   r   
b64_decodeB   s    r   c             C   s   t t| ||j j S )N)r   r   digestdecode)saltvaluekeyr   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jdS )N,:)
separatorszlatin-1)r&   r'   )jsondumpsencode)selfobjr   r   r   r*   V   s    zJSONSerializer.dumpsc             C   s   t j|jdS )Nzlatin-1)r)   loadsr   )r,   datar   r   r   r.   Y   s    zJSONSerializer.loadsN)r	   r
   r   r   r*   r.   r   r   r   r   r%   Q   s   r%   zdjango.core.signingFc       	      C   sd   | j | }d}|r:tj|}t|t|d k r:|}d}t|j }|rRd| }t||dj|S )a  
    Return URL-safe, hmac/SHA1 signed base64 compressed JSON string. If key is
    None, use settings.SECRET_KEY instead.

    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.
    F   T.)r   )r*   zlibcompressr   r   r   TimestampSignersign)	r-   r   r   
serializerr3   r/   Zis_compressed
compressedbase64dr   r   r   r*   ]   s    
r*   c             C   s\   t ||dj| |dj }|dd dk}|r:|dd }t|}|rPtj|}| j|S )z|
    Reverse of dumps(), raise BadSignature if signature fails.

    The serializer is expected to accept a bytestring.
    )r   )max_ageNr0      .)r4   unsignr+   r   r2   
decompressr.   )r   r   r   r6   r9   r8   r<   r/   r   r   r   r.   ~   s    
r.   c               @   s.   e Zd ZdddZdd Zdd Zd	d
 ZdS )r#   Nr'   c             C   sH   |pt j| _|| _tj| jr*td| |p@d| jj| jj	f | _
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   )r,   r   r=   r   r   r   r   __init__   s    zSigner.__init__c             C   s   t | jd || jS )NZsigner)r    r   r   )r,   r   r   r   r   	signature   s    zSigner.signaturec             C   s   d|| j | j|f S )Nz%s%s%s)r=   rC   )r,   r   r   r   r   r5      s    zSigner.signc             C   sN   | j |krtd| j  |j| j d\}}t|| j|r>|S td| d S )NzNo "%s" found in valuer0   zSignature "%s" does not match)r=   r   rsplitr   rC   )r,   Zsigned_valuer   sigr   r   r   r;      s    
zSigner.unsign)Nr'   N)r	   r
   r   rB   rC   r5   r;   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 )	r4   c             C   s   t jjttj S )N)r   base62r+   inttime)r,   r   r   r   	timestamp   s    zTimestampSigner.timestampc                s    d|| j | j f }t j|S )Nz%s%s%s)r=   rI   superr5   )r,   r   )rA   r   r   r5      s    zTimestampSigner.signNc                sn   t  j|}|j| jd\}}tjj|}|dk	rjt|tj	rF|j
 }tj | }||krjtd||f |S )zk
        Retrieve original value and check it wasn't signed more
        than max_age seconds ago.
        r0   NzSignature age %s > %s seconds)rJ   r;   rD   r=   r   rF   r   
isinstancedatetime	timedeltatotal_secondsrH   r   )r,   r   r9   resultrI   Zage)rA   r   r   r;      s    zTimestampSigner.unsign)N)r	   r
   r   rI   r5   r;   __classcell__r   r   )rA   r   r4      s   r4   )r!   ) r   r   rL   r)   rerH   r2   Zdjango.confr   Zdjango.utilsr   Zdjango.utils.cryptor   r   Zdjango.utils.encodingr   Zdjango.utils.module_loadingr   compiler>   	Exceptionr   r   r   r   r    r$   r%   r*   r.   r#   r4   r   r   r   r   <module>"   s.   

!