î

_ÝVï  ã               @   sÀ  d  Z  d d l m 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	 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 m Z m Z d d	 l m Z e j d
 ƒ Z Gd d „  d e ƒ Z Gd d „  d e ƒ Z d d „  Z d d „  Z d d „  Z  d d d „ Z! Gd d „  d e" ƒ Z# d d e# d d d „ Z$ d d e# d d d „ Z% Gd  d! „  d! e" ƒ Z& Gd" 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")
u'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.
é    )Úunicode_literalsN)Úsettings)Úbaseconv)Úconstant_time_compareÚsalted_hmac)ÚRemovedInDjango110Warning)Úforce_bytesÚ	force_strÚ
force_text)Ú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   ú5/tmp/pip-build-ghmbqnp_/Django/django/core/signing.pyr   8   s   r   c               @   s   e  Z d  Z d Z d S)ÚSignatureExpiredz<
    Signature timestamp is older than required max_age
    N)r   r   r   r   r   r   r   r   r   ?   s   r   c             C   s   t  j |  ƒ j d ƒ S)Nó   =)Úbase64Úurlsafe_b64encodeÚstrip)Úsr   r   r   Ú
b64_encodeF   s    r   c             C   s&   d t  |  ƒ d } t j |  | ƒ S)Nr   é   )Úlenr   Úurlsafe_b64decode)r   Úpadr   r   r   Ú
b64_decodeJ   s    r   c             C   s   t  t |  | | ƒ j ƒ  ƒ S)N)r   r   Údigest)ÚsaltÚvalueÚkeyr   r   r   Úbase64_hmacO   s    r#   z%django.core.signing.get_cookie_signerc             C   s2   t  t j ƒ } t t j ƒ } | d | d |  ƒS)Ns   django.http.cookiesr    )r   r   ZSIGNING_BACKENDr   Ú
SECRET_KEY)r    ÚSignerr"   r   r   r   Úget_cookie_signerS   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Ú
separatorsú,ú:zlatin-1)r)   r*   )ÚjsonÚdumpsÚencode)ÚselfÚobjr   r   r   r,   ^   s    zJSONSerializer.dumpsc             C   s   t  j | j d ƒ ƒ S)Nzlatin-1)r+   ÚloadsÚdecode)r.   Údatar   r   r   r0   a   s    zJSONSerializer.loadsN)r   r   r   r   r,   r0   r   r   r   r   r'   Y   s   r'   zdjango.core.signingFc       	      C   s“   | ƒ  j  |  ƒ } d } | r[ t j | ƒ } t | ƒ t | ƒ d k  r[ | } d } q[ n  t | ƒ } | rz d | } n  t | d | ƒj | ƒ S)a‹  
    Returns URL-safe, sha1 signed base64 compressed JSON string. If key is
    None, settings.SECRET_KEY is used instead.

    If compress is True (not the default) checks if compressing using zlib can
    save some space. Prepends 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   ÚTimestampSignerÚsign)	r/   r"   r    Ú
serializerr6   r2   Zis_compressedÚ
compressedÚbase64dr   r   r   r,   e   s    r,   c             C   s   t  t | d | ƒj |  d | ƒƒ } d } | d d … d k r\ | d d … } d } n  t | ƒ } | r€ t j | ƒ } n  | ƒ  j | ƒ S)z}
    Reverse of dumps(), raises BadSignature if signature fails.

    The serializer is expected to accept a bytestring.
    r    Úmax_ageFNr3   r4   T)r   r7   Úunsignr   r5   Ú
decompressr0   )r   r"   r    r9   r<   r;   r>   r2   r   r   r   r0   †   s    '	r0   c               @   sI   e  Z d  Z d d d d d „ Z d d „  Z d d „  Z d	 d
 „  Z d S)r%   Nr*   c             C   sy   | p t  j |  _ t | ƒ |  _ t j |  j ƒ rJ t j d | t	 ƒ n  t | pl 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"   r	   ÚsepÚ_SEP_UNSAFEÚmatchÚwarningsÚwarnr   Ú	__class__r   r   r    )r.   r"   r?   r    r   r   r   Ú__init__œ   s    
	zSigner.__init__c             C   s&   t  |  j d | |  j ƒ } t | ƒ S)NZsigner)r#   r    r"   r	   )r.   r!   Ú	signaturer   r   r   rF   ¦   s    zSigner.signaturec             C   s/   t  | ƒ } t d ƒ | |  j |  j | ƒ f S)Nz%s%s%s)r	   Ústrr?   rF   )r.   r!   r   r   r   r8   «   s    zSigner.signc             C   s‚   t  | ƒ } |  j | k r1 t d |  j ƒ ‚ n  | j |  j d ƒ \ } } t | |  j | ƒ ƒ rn t | ƒ St d | ƒ ‚ d  S)NzNo "%s" found in valuer3   zSignature "%s" does not match)r	   r?   r   Úrsplitr   rF   r
   )r.   Zsigned_valuer!   Úsigr   r   r   r=   ¯   s    
zSigner.unsign)r   r   r   rE   rF   r8   r=   r   r   r   r   r%   š   s   
r%   c                   sC   e  Z d  Z d d „  Z ‡  f d d †  Z d ‡  f d d † Z ‡  S)r7   c             C   s   t  j j t t j ƒ  ƒ ƒ S)N)r   Úbase62r-   ÚintÚtime)r.   r   r   r   Ú	timestamp»   s    zTimestampSigner.timestampc                sD   t  | ƒ } t d ƒ | |  j |  j ƒ  f } t t |  ƒ j | ƒ S)Nz%s%s%s)r	   rG   r?   rM   Úsuperr7   r8   )r.   r!   )rD   r   r   r8   ¾   s    "zTimestampSigner.signNc                s®   t  t |  ƒ j | ƒ } | j |  j d ƒ \ } } t j j | ƒ } | d k	 rª t | t	 j
 ƒ rr | j ƒ  } n  t j ƒ  | } | | k rª t d | | f ƒ ‚ qª n  | S)zk
        Retrieve original value and check it wasn't signed more
        than max_age seconds ago.
        r3   NzSignature age %s > %s seconds)rN   r7   r=   rH   r?   r   rJ   r1   Ú
isinstanceÚdatetimeÚ	timedeltaÚtotal_secondsrL   r   )r.   r!   r<   ÚresultrM   Zage)rD   r   r   r=   Ã   s    zTimestampSigner.unsign)r   r   r   rM   r8   r=   r   r   )rD   r   r7   ¹   s   r7   )(r   Ú
__future__r   r   rP   r+   ÚrerL   rB   r5   Zdjango.confr   Zdjango.utilsr   Zdjango.utils.cryptor   r   Zdjango.utils.deprecationr   Zdjango.utils.encodingr   r	   r
   Zdjango.utils.module_loadingr   Úcompiler@   Ú	Exceptionr   r   r   r   r#   r&   Úobjectr'   r,   r0   r%   r7   r   r   r   r   Ú<module>"   s4   !