aboutsummaryrefslogtreecommitdiff
path: root/okupy
diff options
context:
space:
mode:
authorMichał Górny <mgorny@gentoo.org>2013-08-21 10:16:56 +0200
committerMichał Górny <mgorny@gentoo.org>2013-08-21 10:16:56 +0200
commit3b731f58b2c6119006c1b8ee5475aee4d2b512c1 (patch)
tree080180922126ea57f549d85919078b65042cca02 /okupy
parentUse AES as OkupyCipher. (diff)
downloadidentity.gentoo.org-3b731f58b2c6119006c1b8ee5475aee4d2b512c1.tar.gz
identity.gentoo.org-3b731f58b2c6119006c1b8ee5475aee4d2b512c1.tar.bz2
identity.gentoo.org-3b731f58b2c6119006c1b8ee5475aee4d2b512c1.zip
'Pack' session id into binary string before encrypting.
Since it's basically base36, we can treat it as base64 and pack 3:4. This way, with the random padding added, we end up taking one block of ciphertext less and we have shorter and more unique tokens.
Diffstat (limited to 'okupy')
-rw-r--r--okupy/common/crypto.py28
1 files changed, 25 insertions, 3 deletions
diff --git a/okupy/common/crypto.py b/okupy/common/crypto.py
index c36e51f..1efb00f 100644
--- a/okupy/common/crypto.py
+++ b/okupy/common/crypto.py
@@ -24,6 +24,18 @@ def ub32decode(text):
return base64.b32decode(text, casefold=True)
+def ub64encode(text):
+ """ Encode text as unpadded base64. """
+ return base64.b64encode(text).rstrip('=')
+
+
+def ub64decode(text):
+ """ decode text from unpadded base64. """
+ # add missing padding if necessary
+ text += '=' * (-len(text) % 4)
+ return base64.b64decode(text)
+
+
class OkupyCipher(object):
""" Symmetric cipher using django's SECRET_KEY. """
@@ -97,6 +109,7 @@ class SessionRefCipher(object):
cache_key_prefix = 'django.contrib.sessions.cache'
session_id_length = 32
random_prefix_bytes = 4
+ ciphertext_length = session_id_length*3/4 + random_prefix_bytes
def encrypt(self, session):
"""
@@ -118,8 +131,17 @@ class SessionRefCipher(object):
session_id = session_id[len(self.cache_key_prefix):]
assert(len(session_id) == self.session_id_length)
+ # now's another curious trick: session id consists
+ # of [a-z][0-9]. it's basically base36 but since decoding
+ # that is harsh, let's just treat it as base64. that's
+ # going to pack it into 3/4 original size, that is 24 bytes.
+ # then, with random prefix prepended we will fit into one
+ # block of ciphertext less.
+ session_id = ub64decode(session_id)
+
data = (cipher.rng.read(self.random_prefix_bytes)
- + session_id.encode('utf8'))
+ + session_id)
+ assert(len(data) == self.ciphertext_length)
session['encrypted_id'] = ub32encode(
cipher.encrypt(data)).lower()
session.save()
@@ -133,12 +155,12 @@ class SessionRefCipher(object):
try:
session_id = cipher.decrypt(ub32decode(eid),
- self.session_id_length
- + self.random_prefix_bytes)
+ self.ciphertext_length)
except (TypeError, ValueError):
pass
else:
session_id = session_id[self.random_prefix_bytes:]
+ session_id = ub64encode(session_id)
session = SessionStore(session_key=session_id)
if session.get('encrypted_id') == eid:
# circular import