B
    CVvgã  ã               @   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-install-o3oxmrkh/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  | ¡ 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)ú,ú:)Ú
separatorszlatin-1)ÚjsonÚdumpsÚencode)ÚselfÚobjr   r   r   r-   V   s    zJSONSerializer.dumpsc             C   s   t  | d¡¡S )Nzlatin-1)r,   Úloadsr   )r/   Údatar   r   r   r1   Y   s    zJSONSerializer.loadsN)r
   r   r   r   r-   r1   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)r0   r"   r    r3   r4   r   r   r   r-   ]   s    r-   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    )r3   Úmax_age)r5   Úunsign_object)r   r"   r    r3   r7   r   r   r   r1   q   s    r1   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   )r/   r"   r9   r    r   r   r   r   Ú__init__~   s    zSigner.__init__c             C   s   t | jd || j| jd�S )NÚsigner)r   )r#   r    r"   r   )r/   r!   r   r   r   Ú	signature‹   s    zSigner.signaturec             C   s   t | jd || j| jd�S )Nr?   )r   )r#   r    r"   Úlegacy_algorithm)r/   r!   r   r   r   Ú_legacy_signatureŽ   s    zSigner._legacy_signaturec             C   s   d|| j |  |¡f S )Nz%s%s%s)r9   r@   )r/   r!   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)r9   r	   Úrsplitr   r@   rA   rB   )r/   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.
        FrD   TÚ.)r-   Úzlibr4   r   r   r   rC   )r/   r0   r3   r4   r2   Zis_compressedÚ
compressedÚbase64dr   r   r   r6   ¢   s    

zSigner.sign_objectc             K   sT   | j |f|Ž ¡ }|d d… dk}|r2|dd … }t|ƒ}|rHt |¡}|ƒ  |¡S )NrD   ó   .)rG   r.   r   rI   Ú
decompressr1   )r/   Z
signed_objr3   ÚkwargsrK   rM   r2   r   r   r   r8   »   s    
zSigner.unsign_object)Nr*   NN)r
   r   r   rA   r>   r@   rB   rC   rG   r(   r6   r8   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 )	r5   c             C   s   t j tt ¡ ƒ¡S )N)r   Úbase62r.   ÚintÚtime)r/   r   r   r   Ú	timestampË   s    zTimestampSigner.timestampc                s    d|| j |  ¡ f }tƒ  |¡S )Nz%s%s%s)r9   rR   ÚsuperrC   )r/   r!   )r=   r   r   rC   Î   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.
        rD   NzSignature age %s > %s seconds)rS   rG   rE   r9   r   rO   r   Ú
isinstanceÚdatetimeÚ	timedeltaÚtotal_secondsrQ   r   )r/   r!   r7   ÚresultrR   Zage)r=   r   r   rG   Ò   s    zTimestampSigner.unsign)N)r
   r   r   rR   rC   rG   Ú__classcell__r   r   )r=   r   r5   É   s   r5   )r   )r$   ) r   r   rU   r,   rQ   rI   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(   r-   r1   r&   r5   r   r   r   r   Ú<module>"   s.   

	O