Fixed #19980: Signer broken for binary keys (with non-ASCII chars).
With this pull request, request #878 should considered closed. Thanks to nvie for the patch.
This commit is contained in:
parent
8274fa60f8
commit
a8ba76c2d3
|
@ -76,7 +76,8 @@ def base64_hmac(salt, value, key):
|
||||||
|
|
||||||
def get_cookie_signer(salt='django.core.signing.get_cookie_signer'):
|
def get_cookie_signer(salt='django.core.signing.get_cookie_signer'):
|
||||||
Signer = import_string(settings.SIGNING_BACKEND)
|
Signer = import_string(settings.SIGNING_BACKEND)
|
||||||
return Signer('django.http.cookies' + settings.SECRET_KEY, salt=salt)
|
key = force_bytes(settings.SECRET_KEY)
|
||||||
|
return Signer(b'django.http.cookies' + key, salt=salt)
|
||||||
|
|
||||||
|
|
||||||
class JSONSerializer(object):
|
class JSONSerializer(object):
|
||||||
|
@ -148,9 +149,9 @@ class Signer(object):
|
||||||
|
|
||||||
def __init__(self, key=None, sep=':', salt=None):
|
def __init__(self, key=None, sep=':', salt=None):
|
||||||
# Use of native strings in all versions of Python
|
# Use of native strings in all versions of Python
|
||||||
self.sep = str(sep)
|
self.sep = force_str(sep)
|
||||||
self.key = str(key or settings.SECRET_KEY)
|
self.key = key or settings.SECRET_KEY
|
||||||
self.salt = str(salt or
|
self.salt = force_str(salt or
|
||||||
'%s.%s' % (self.__class__.__module__, self.__class__.__name__))
|
'%s.%s' % (self.__class__.__module__, self.__class__.__name__))
|
||||||
|
|
||||||
def signature(self, value):
|
def signature(self, value):
|
||||||
|
|
|
@ -36,10 +36,13 @@ def salted_hmac(key_salt, value, secret=None):
|
||||||
if secret is None:
|
if secret is None:
|
||||||
secret = settings.SECRET_KEY
|
secret = settings.SECRET_KEY
|
||||||
|
|
||||||
|
key_salt = force_bytes(key_salt)
|
||||||
|
secret = force_bytes(secret)
|
||||||
|
|
||||||
# We need to generate a derived key from our base key. We can do this by
|
# We need to generate a derived key from our base key. We can do this by
|
||||||
# passing the key_salt and our base key through a pseudo-random function and
|
# passing the key_salt and our base key through a pseudo-random function and
|
||||||
# SHA1 works nicely.
|
# SHA1 works nicely.
|
||||||
key = hashlib.sha1((key_salt + secret).encode('utf-8')).digest()
|
key = hashlib.sha1(key_salt + secret).digest()
|
||||||
|
|
||||||
# If len(key_salt + secret) > sha_constructor().block_size, the above
|
# If len(key_salt + secret) > sha_constructor().block_size, the above
|
||||||
# line is redundant and could be replaced by key = key_salt + secret, since
|
# line is redundant and could be replaced by key = key_salt + secret, since
|
||||||
|
|
|
@ -2,6 +2,7 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.core import signing
|
from django.core import signing
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
@ -62,3 +63,18 @@ class SignedCookieTest(TestCase):
|
||||||
request.get_signed_cookie, 'c', max_age=10)
|
request.get_signed_cookie, 'c', max_age=10)
|
||||||
finally:
|
finally:
|
||||||
time.time = _time
|
time.time = _time
|
||||||
|
|
||||||
|
def test_signed_cookies_with_binary_key(self):
|
||||||
|
def restore_secret_key(prev):
|
||||||
|
settings.SECRET_KEY = prev
|
||||||
|
|
||||||
|
self.addCleanup(restore_secret_key, settings.SECRET_KEY)
|
||||||
|
|
||||||
|
settings.SECRET_KEY = b'\xe7'
|
||||||
|
|
||||||
|
response = HttpResponse()
|
||||||
|
response.set_signed_cookie('c', 'hello')
|
||||||
|
|
||||||
|
request = HttpRequest()
|
||||||
|
request.COOKIES['c'] = response.cookies['c'].value
|
||||||
|
self.assertEqual(request.get_signed_cookie('c'), 'hello')
|
||||||
|
|
|
@ -105,6 +105,12 @@ class TestSigner(TestCase):
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
signing.BadSignature, signing.loads, transform(encoded))
|
signing.BadSignature, signing.loads, transform(encoded))
|
||||||
|
|
||||||
|
def test_works_with_non_ascii_keys(self):
|
||||||
|
binary_key = b'\xe7' # Set some binary (non-ASCII key)
|
||||||
|
|
||||||
|
s = signing.Signer(binary_key)
|
||||||
|
self.assertEquals('foo:6NB0fssLW5RQvZ3Y-MTerq2rX7w', s.sign('foo'))
|
||||||
|
|
||||||
|
|
||||||
class TestTimestampSigner(TestCase):
|
class TestTimestampSigner(TestCase):
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue