changeset 84:5a3c91771914

Add message signing and timestamping utility. Based on itsdangerous: http://packages.python.org/itsdangerous/
author Daniele Nicolodi <daniele@grinta.net>
date Sun, 21 Aug 2011 16:10:23 +0200
parents da7cab4398c3
children ff2da2018071
files buildout.cfg src/ltpdarepo/sign.py src/ltpdarepo/tests/test_sign.py
diffstat 3 files changed, 48 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/buildout.cfg	Sun Aug 21 16:10:23 2011 +0200
+++ b/buildout.cfg	Sun Aug 21 16:10:23 2011 +0200
@@ -9,6 +9,7 @@
      WTForms
      ordereddict
      argparse
+     itsdangerous
      ltpdarepo
 interpreter = python
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ltpdarepo/sign.py	Sun Aug 21 16:10:23 2011 +0200
@@ -0,0 +1,24 @@
+from flask import current_app as app, request
+from itsdangerous import URLSafeTimedSerializer, BadSignature, SignatureExpired
+
+
+class Signer(URLSafeTimedSerializer):
+    """Subclass `itsdangerouns.URLSafeTimedSerializer` setting the
+    default secret to the application secret key and the salt to
+    `request.host`. Overrides `dumps()` and `loads()` methods with
+    custom versions that substitute `~` for `_` in the signed string."""
+    
+    def __init__(self, secret=None, salt=None):
+        if secret is None:
+            secret = app.config['SECRET_KEY']
+        if salt is None:
+            salt = request.host
+        super(Signer, self).__init__(secret, salt)
+
+    def dumps(self, obj):
+        string = super(Signer, self).dumps(obj)
+        return string.replace('_', '~')
+
+    def loads(self, string, maxage=None):
+        string = string.replace('~', '_')
+        return super(Signer, self).loads(string, max_age=maxage)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ltpdarepo/tests/test_sign.py	Sun Aug 21 16:10:23 2011 +0200
@@ -0,0 +1,23 @@
+import unittest2 as unittest
+
+from ltpdarepo.sign import Signer, BadSignature
+
+class TestCase(unittest.TestCase):
+
+    def test_signer(self):
+        s = Signer('secret', 'salt')
+        value = 'foo'
+        token = s.dumps(value)
+        self.assertEqual(s.loads(token), value)
+
+    def test_tempering(self):
+        s = Signer('secret', 'salt')
+        value = 'foo'
+        token = s.dumps(value)
+        val, timestamp, signature = token.split('.')
+        val = val.replace(val[0], val[1])
+        self.assertRaises(BadSignature, lambda: s.loads('.'.join((val, timestamp, signature))))
+        timestamp = timestamp.replace(timestamp[0], timestamp[1])
+        self.assertRaises(BadSignature, lambda: s.loads('.'.join((val, timestamp, signature))))
+        signature = signature.replace(signature[0], signature[1])
+        self.assertRaises(BadSignature, lambda: s.loads('.'.join((val, timestamp, signature))))