diff --git a/django_openid/auth.py b/django_openid/auth.py index 7301c5e..c4697d7 100644 --- a/django_openid/auth.py +++ b/django_openid/auth.py @@ -208,7 +208,7 @@ def show_associate(self, request, openid=None): return self.need_authenticated_user(request) try: next = signed.loads( - request.REQUEST.get('next', ''), extra_salt=self.salt_next + request.REQUEST.get('next', ''), extra_key=self.salt_next ) except ValueError: next = '' @@ -218,9 +218,9 @@ def show_associate(self, request, openid=None): 'specific_openid': openid, 'next': next and request.REQUEST.get('next', '') or None, 'openid_token': signed.dumps( - # Use user.id as part of extra_salt to prevent attackers from + # Use user.id as part of extra_key to prevent attackers from # creating their own openid_token for use in CSRF attack - openid, extra_salt = self.associate_salt + str(request.user.id) + openid, extra_key = self.associate_salt + str(request.user.id) ), }) @@ -229,7 +229,7 @@ def do_associate(self, request): try: openid = signed.loads( request.POST.get('openid_token', ''), - extra_salt = self.associate_salt + str(request.user.id) + extra_key = self.associate_salt + str(request.user.id) ) except signed.BadSignature: return self.show_error(request, self.csrf_failed_message) @@ -262,7 +262,7 @@ def do_associations(self, request): try: todelete = signed.loads( request.POST['todelete'], - extra_salt = self.associate_delete_salt + extra_key = self.associate_delete_salt ) if todelete['user_id'] != request.user.id: message = self.associate_tampering_message @@ -285,7 +285,7 @@ def do_associations(self, request): 'user_id': request.user.id, 'association_id': association.id, 'openid': association.openid, - }, extra_salt = self.associate_delete_salt), + }, extra_key = self.associate_delete_salt), }) return self.render(request, self.associations_template, { 'openids': openids, diff --git a/django_openid/consumer.py b/django_openid/consumer.py index 37d42a0..64e4f87 100644 --- a/django_openid/consumer.py +++ b/django_openid/consumer.py @@ -115,7 +115,7 @@ def __init__(self, persist_class=CookiePersist): self.persist = persist_class() def sign_next(self, url): - return signed.dumps(url, extra_salt = self.salt_next) + return signed.dumps(url, extra_key = self.salt_next) def render(self, request, template, context=None): context = context or {} @@ -159,7 +159,7 @@ def do_index(self, request, extra_message=None): def show_login(self, request, message=None): try: next = signed.loads( - request.REQUEST.get('next', ''), extra_salt=self.salt_next + request.REQUEST.get('next', ''), extra_key=self.salt_next ) except ValueError: next = '' @@ -207,7 +207,7 @@ def get_on_complete_url(self, request, on_complete_url=None): on_complete_url = self.ensure_absolute_url(request, on_complete_url) try: next = signed.loads( - request.POST.get('next', ''), extra_salt=self.salt_next + request.POST.get('next', ''), extra_key=self.salt_next ) except ValueError: return on_complete_url @@ -304,7 +304,7 @@ def redirect_if_valid_next(self, request): "Logic for checking if a signed ?next= token is included in request" try: next = signed.loads( - request.REQUEST.get('next', ''), extra_salt=self.salt_next + request.REQUEST.get('next', ''), extra_key=self.salt_next ) return HttpResponseRedirect(next) except ValueError: @@ -435,7 +435,7 @@ def persist_openid(self, request, response, openid_object): response.set_cookie( key = self.cookie_key, value = signed.dumps( - openid_object, compress = True, extra_salt = self.extra_salt + openid_object, compress = True, extra_key = self.extra_salt ), max_age = self.cookie_max_age, expires = self.cookie_expires, @@ -455,7 +455,7 @@ def do_debug(self, request): raise Http404 if self.cookie_key in request.COOKIES: obj = signed.loads( - request.COOKIES[self.cookie_key], extra_salt = self.extra_salt + request.COOKIES[self.cookie_key], extra_key = self.extra_salt ) assert False, (obj, obj.__dict__) assert False, 'no cookie named %s' % self.cookie_key @@ -469,7 +469,7 @@ def process_request(self, request): if cookie_value: try: request.openid = signed.loads( - cookie_value, extra_salt = self.extra_salt + cookie_value, extra_key = self.extra_salt ) request.openids = [request.openid] except ValueError: # Signature failed diff --git a/django_openid/provider.py b/django_openid/provider.py index 58c134d..4efc907 100644 --- a/django_openid/provider.py +++ b/django_openid/provider.py @@ -69,7 +69,7 @@ def show_landing_page(self, request, orequest): def stash_incomplete_orequest(self, request, response, orequest): response.set_cookie( self.incomplete_orequest_cookie_key, signed.dumps( - orequest, extra_salt = self.orequest_salt + orequest, extra_key = self.orequest_salt ) ) @@ -137,7 +137,7 @@ def extract_incomplete_orequest(self, request): try: return signed.loads(request.COOKIES.get( self.incomplete_orequest_cookie_key, '' - ), extra_salt = self.orequest_salt) + ), extra_key = self.orequest_salt) except signed.BadSignature: return None diff --git a/django_openid/signed.py b/django_openid/signed.py index ae3890c..0588daf 100644 --- a/django_openid/signed.py +++ b/django_openid/signed.py @@ -8,7 +8,7 @@ There are two components here, separatad by a '.'. The first component is a URLsafe base64 encoded pickle of the object passed to dumps(). The second -component is a base64 encoded SHA1 hash of "$first_component.$secret" +component is a base64 encoded hmac/SHA1 hash of "$first_component.$secret" Calling signed.loads(s) checks the signature BEFORE unpickling the object - this protects against malformed pickle attacks. If the signature fails, a @@ -39,16 +39,16 @@ from django.utils.hashcompat import sha_constructor import hmac -def dumps(obj, secret = None, compress = False, extra_salt = ''): +def dumps(obj, key = None, compress = False, extra_key = ''): """ - Returns URL-safe, sha1 signed base64 compressed pickle. If secret is + Returns URL-safe, sha1 signed base64 compressed pickle. 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. - extra_salt can be used to further salt the hash, in case you're worried + extra_key can be used to further salt the hash, in case you're worried that the NSA might try to brute-force your SHA-1 protected secret. """ pickled = pickle.dumps(obj) @@ -62,14 +62,14 @@ def dumps(obj, secret = None, compress = False, extra_salt = ''): base64d = encode(pickled).strip('=') if is_compressed: base64d = '.' + base64d - return sign(base64d, (secret or settings.SECRET_KEY) + extra_salt) + return sign(base64d, (key or settings.SECRET_KEY) + extra_key) -def loads(s, secret = None, extra_salt = ''): +def loads(s, key = None, extra_key = ''): "Reverse of dumps(), raises ValueError if signature fails" if isinstance(s, unicode): s = s.encode('utf8') # base64 works on bytestrings, not on unicodes try: - base64d = unsign(s, (secret or settings.SECRET_KEY) + extra_salt) + base64d = unsign(s, (key or settings.SECRET_KEY) + extra_key) except ValueError: raise decompress = False diff --git a/django_openid/tests/consumer_tests.py b/django_openid/tests/consumer_tests.py index 29f2e6a..c20988a 100644 --- a/django_openid/tests/consumer_tests.py +++ b/django_openid/tests/consumer_tests.py @@ -162,7 +162,7 @@ def testLogin(self): # Decrypt the cookie and check it's the right thing cookie = response.cookies['openid'].value openid = signed.loads( - cookie, extra_salt = MyCookieConsumer().extra_salt + cookie, extra_key = MyCookieConsumer().extra_salt ) self.assertEqual(openid.openid, 'http://simonwillison.net/')