diff options
author | Alexander Sulfrian <alexander@sulfrian.net> | 2016-01-24 03:55:49 +0100 |
---|---|---|
committer | Alexander Sulfrian <alexander@sulfrian.net> | 2016-02-02 04:22:16 +0100 |
commit | 5e7e7fc832d26178a6036ed483fe3cfffe2b22b2 (patch) | |
tree | c74302270b7c262d744876f1d2f93bc84c44a2ba /accounts/utils/sessions.py | |
parent | 6eb1db6bff15e1611767f5219ee1b4ea558e3d28 (diff) | |
download | web-5e7e7fc832d26178a6036ed483fe3cfffe2b22b2.tar.gz web-5e7e7fc832d26178a6036ed483fe3cfffe2b22b2.tar.bz2 web-5e7e7fc832d26178a6036ed483fe3cfffe2b22b2.zip |
Encrypt the session data by default
Before we just encrypted the password, now we encrypt the whole session
information by default.
Diffstat (limited to 'accounts/utils/sessions.py')
-rw-r--r-- | accounts/utils/sessions.py | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/accounts/utils/sessions.py b/accounts/utils/sessions.py new file mode 100644 index 0000000..cd12030 --- /dev/null +++ b/accounts/utils/sessions.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +from Crypto import Random +from Crypto.Cipher import AES +from flask import current_app +from flask.sessions import TaggedJSONSerializer, SecureCookieSessionInterface +from itsdangerous import BadPayload + + +def _pad(value, block_size): + padding = block_size - len(value) % block_size + return value + (padding * chr(padding)) + + +def _unpad(value): + pad_length = ord(value[len(value)-1:]) + return value[:-pad_length] + + +class EncryptedSerializer(TaggedJSONSerializer): + + def __init__(self): + self.block_size = AES.block_size + + def _cipher(self, iv): + return AES.new( + current_app.config['SESSION_ENCRYPTION_KEY'], + AES.MODE_CBC, iv) + + def dumps(self, value): + """ + Encrypt the serialized values with `config.SESSION_ENCRYPTION_KEY`. + The key must be 32 bytes long. + """ + assert len(current_app.config['SESSION_ENCRYPTION_KEY']) == 32 + + serialized_value = super(EncryptedSerializer, self).dumps(value) + + raw = _pad(serialized_value, self.block_size) + iv = Random.new().read(self.block_size) + return iv + self._cipher(iv).encrypt(raw) + + def loads(self, value): + """ + Decrypt the given serialized session data with + `config.SESSION_ENCRYPTION_KEY`. + """ + iv = value[:self.block_size] + raw = self._cipher(iv).decrypt(value[AES.block_size:]) + return super(EncryptedSerializer, self).loads(_unpad(raw)) + + +class EncryptedSessionInterface(SecureCookieSessionInterface): + serializer = EncryptedSerializer() + + def open_session(self, *args, **kwargs): + try: + parent = super(EncryptedSessionInterface, self) + return parent.open_session(*args, **kwargs) + except BadPayload: + return self.session_class() |