Skip to content

Commit dae676f

Browse files
author
Shane R. Spencer
committed
Initial Version
1 parent 1b102cc commit dae676f

File tree

5 files changed

+146
-0
lines changed

5 files changed

+146
-0
lines changed

COPYING

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2013 Shane R. Spencer
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of
4+
this software and associated documentation files (the "Software"), to deal in
5+
the Software without restriction, including without limitation the rights to
6+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7+
of the Software, and to permit persons to whom the Software is furnished to do
8+
so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include *.md

setup.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
from setuptools import setup, find_packages
5+
6+
import tornadoencookie
7+
8+
with open('README.md') as stream:
9+
long_desc = stream.read()
10+
11+
setup(
12+
name = tornadoencookie.__name__,
13+
version = tornadoencookie.__version__,
14+
author = tornadoencookie.__author__,
15+
author_email = tornadoencookie.__email__,
16+
packages = ['tornadoencookie'],
17+
license = tornadoencookie.__license__,
18+
description = tornadoencookie.__description__,
19+
url='https://github.com/whardier/tornado-encookie',
20+
long_description = long_desc,
21+
install_requires=[
22+
'tornado',
23+
'pycrypto',
24+
],
25+
classifiers = [
26+
'Programming Language :: Python',
27+
'Operating System :: OS Independent',
28+
'Development Status :: 1 - Planning',
29+
'Environment :: Plugins',
30+
'Framework :: Tornado',
31+
'Intended Audience :: Developers',
32+
'Intended Audience :: Information Technology',
33+
'License :: OSI Approved :: MIT License',
34+
'Natural Language :: English',
35+
'Topic :: Internet :: WWW/HTTP :: Session',
36+
],
37+
)
38+

tornadoencookie/__init__.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/usr/bin/env python
2+
# -*- coding: UTF-8 -*-
3+
4+
"""tornado-encookie"""
5+
6+
__name__ = "tornadoencookie"
7+
__author__ = 'Shane R. Spencer'
8+
__email__ = "shane@bogomip.com"
9+
__license__ = 'None'
10+
__copyright__ = '2013 Shane R. Spencer'
11+
__version__ = '0.0.1'
12+
__status__ = "Prototype"
13+
__description__ = "Encrypted cookie support for the Tornado Web Framework"
14+
15+

tornadoencookie/encookie.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
from Crypto.Cipher import AES
2+
import base64
3+
4+
class EncookieManager(object):
5+
6+
BLOCK_SIZE = 32
7+
PADDING = '\0'
8+
9+
def __init__(self, handler):
10+
self.handler = handler
11+
self.secret = ''
12+
self.__setup_encookie()
13+
14+
def __setup_encookie(self):
15+
self.__setup_settings()
16+
self.cipher = AES.new(self.secret)
17+
18+
def __setup_settings(self):
19+
self.handler.require_setting("encookie_secret", "encrypted cookies")
20+
self.secret = self.handler.settings.get('encookie_secret')
21+
22+
def _pad(self, value):
23+
return value + (self.BLOCK_SIZE - len(value) % self.BLOCK_SIZE) * self.PADDING
24+
25+
def _encrypt(self, value):
26+
return base64.b64encode(self.cipher.encrypt(self._pad(value))).decode('utf-8')
27+
28+
def _decrypt(self, value):
29+
return self.cipher.decrypt(base64.b64decode(value.encode('utf-8'))).decode('utf-8').rstrip(self.PADDING)
30+
31+
def get_cookie(self, name, default=None):
32+
encrypted_value = self.handler.get_cookie(name)
33+
if not encrypted_value:
34+
return default
35+
return self._decrypt(encrypted_value)
36+
37+
def set_cookie(self, name, value, domain=None, expires=None, path="/",
38+
expires_days=None, **kwargs):
39+
encrypted_value = self._encrypt(value)
40+
self.handler.set_cookie(name, encrypted_value, domain=domain, expires=expires, path=path,
41+
expires_days=expires_days, **kwargs)
42+
43+
def set_secure_cookie(self, name, value, expires_days=30, **kwargs):
44+
encrypted_value = self._encrypt(value)
45+
self.handler.set_secure_cookie(name, encrypted_value,
46+
expires_days=expires_days, **kwargs)
47+
48+
def get_secure_cookie(self, name, value=None, max_age_days=31):
49+
if value is None:
50+
value = self.handler.get_cookie(name)
51+
encrypted_value = self.handler.get_secure_cookie(name, value, max_age_days=max_age_days)
52+
if encrypted_value:
53+
return self._decrypt(encrypted_value.decode('utf-8'))
54+
else:
55+
return None
56+
57+
class EncookieMixin(object):
58+
@property
59+
def encookie(self):
60+
'''
61+
Returns an encookie instance
62+
'''
63+
64+
return create_mixin(self, '__encookie_manager', EncookieManager)
65+
66+
class ConfigurationError(Exception):
67+
pass
68+
69+
def create_mixin(context, manager_property, manager_class):
70+
if not hasattr(context, manager_property):
71+
setattr(context, manager_property, manager_class(context))
72+
return getattr(context, manager_property)
73+

0 commit comments

Comments
 (0)