o 3a@sdZddlZddlZddlZddlZddlZddlmZddlm Z ddl m Z m Z ddl mZddlmZddlmZed ZGd d d eZGd d d eZddZddZd$ddZd%ddZGdddZddedfddZddedfddZGd d!d!ZGd"d#d#eZdS)&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@eZdZdZdS) BadSignaturezSignature does not match.N__name__ __module__ __qualname____doc__rr5/usr/lib/python3/dist-packages/django/core/signing.pyr 4r c@r )SignatureExpiredz3Signature timestamp is older than required max_age.Nr rrrrr9rrcCst|dS)N=)base64urlsafe_b64encodestrip)srrr b64_encode>rcCs dt| d}t||S)Nr)lenrurlsafe_b64decode)rpadrrr b64_decodeBsrsha1cCstt||||dS)N algorithm)rrdigestdecode)saltvaluekeyr"rrr base64_hmacGsr(%django.core.signing.get_cookie_signercCs$ttj}ttj}|d||dS)Nsdjango.http.cookiesr%)rrSIGNING_BACKENDr SECRET_KEY)r%Signerr'rrrget_cookie_signerKs  r.c@s eZdZdZddZddZdS)JSONSerializerzW Simple wrapper around json to be used in signing.dumps and signing.loads. cCstj|dddS)N),:) separatorslatin-1)jsondumpsencode)selfobjrrrr5VzJSONSerializer.dumpscCst|dS)Nr3)r4loadsr$)r7datarrrr:YrzJSONSerializer.loadsN)r r rrr5r:rrrrr/Qs r/zdjango.core.signingFcCt||dj|||dS)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*) serializercompress)TimestampSigner sign_object)r8r'r%r=r>rrrr5]sr5cCr<)z| Reverse of dumps(), raise BadSignature if signature fails. The serializer is expected to accept a bytestring. r*)r=max_age)r? unsign_object)rr'r%r=rArrrr:qsr:c@sTeZdZdZdddZddZdd Zd d Zd d Ze dfddZ e fddZ dS)r-r Nr1cCsT|ptj|_||_t|jrtd||p d|jj|jj f|_ |p&tj |_ dS)NzJUnsafe Signer separator: %r (cannot be empty or consist of only A-z0-9-_=)z%s.%s) rr,r'sep _SEP_UNSAFEmatch ValueError __class__r r r%DEFAULT_HASHING_ALGORITHMr")r7r'rCr%r"rrr__init__~s  zSigner.__init__cCt|jd||j|jdSNsignerr!)r(r%r'r"r7r&rrr signatureszSigner.signaturecCrJrK)r(r%r'legacy_algorithmrMrrr_legacy_signatureszSigner._legacy_signaturecCsd||j||fSNz%s%s%s)rCrNrMrrrsignsz Signer.signcCs`|j|vr td|j||jd\}}t|||s(|jr*t|||r*|Std|)NzNo "%s" found in valuezSignature "%s" does not match)rCr rsplitrrNrOrP)r7 signed_valuer&sigrrrunsigns  z Signer.unsignFcCs\||}d}|rt|}t|t|dkr|}d}t|}|r)d|}||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. FrST.)r5zlibr>rrr$rR)r7r8r=r>r; is_compressed compressedbase64drrrr@s    zSigner.sign_objectcKsX|j|fi|}|dddk}|r|dd}t|}|r&t|}||S)NrS.)rWr6rrY decompressr:)r7 signed_objr=kwargsr\r^r;rrrrBs   zSigner.unsign_object)Nr1NN) r r rrOrIrNrPrRrWr/r@rBrrrrr-zs   r-cs2eZdZddZfddZdfdd ZZS) r?cCstjttSN)rbase62r6inttime)r7rrr timestampr9zTimestampSigner.timestampcs d||j|f}t|SrQ)rCresuperrRrMrGrrrRs zTimestampSigner.signNcsnt|}||jd\}}tj|}|dur5t|tj r#| }t |}||kr5t d||f|S)zk Retrieve original value and check it wasn't signed more than max_age seconds ago. rSNzSignature age %s > %s seconds) rfrWrTrCrrbr$ isinstancedatetime timedelta total_secondsrdr)r7r&rAresultreagergrrrWs     zTimestampSigner.unsignra)r r rrerRrW __classcell__rrrgrr?s r?)r )r)) rrrir4rdrY django.confr django.utilsrdjango.utils.cryptorrdjango.utils.encodingrdjango.utils.module_loadingrdjango.utils.regex_helperrrD Exceptionr rrrr(r.r/r5r:r-r?rrrrs0#         O