summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2011-10-14 20:41:21 -0400
committerChris McDonough <chrism@plope.com>2011-10-14 20:41:21 -0400
commit5f0d6d54572a4c2182d730daf5f0a683cabb36ca (patch)
tree65b2a5aeff45e274310acecdd76db926cf3cbaf0
parent5a20b131b921362785dda87409ca8eb3a1a9c6a1 (diff)
parentd1527f421d8ad6163304cbb3bcec3b2c2124c9dc (diff)
downloadpyramid-5f0d6d54572a4c2182d730daf5f0a683cabb36ca.tar.gz
pyramid-5f0d6d54572a4c2182d730daf5f0a683cabb36ca.tar.bz2
pyramid-5f0d6d54572a4c2182d730daf5f0a683cabb36ca.zip
Merge branch 'master' of github.com:Pylons/pyramid
-rw-r--r--pyramid/authentication.py6
-rw-r--r--pyramid/session.py12
-rw-r--r--pyramid/util.py20
3 files changed, 28 insertions, 10 deletions
diff --git a/pyramid/authentication.py b/pyramid/authentication.py
index 955e870b4..3909ce2d8 100644
--- a/pyramid/authentication.py
+++ b/pyramid/authentication.py
@@ -22,6 +22,8 @@ from pyramid.interfaces import IDebugLogger
from pyramid.security import Authenticated
from pyramid.security import Everyone
+from pyramid.util import strings_differ
+
VALID_TOKEN = re.compile(r"^[A-Za-z][A-Za-z0-9+_-]*$")
class CallbackAuthenticationPolicy(object):
@@ -485,7 +487,9 @@ def parse_ticket(secret, ticket, ip):
expected = calculate_digest(ip, timestamp, secret,
userid, tokens, user_data)
- if expected != digest:
+ # Avoid timing attacks (see
+ # http://seb.dbzteam.org/crypto/python-oauth-timing-hmac.pdf)
+ if strings_differ(expected, digest):
raise BadTicket('Digest signature is not correct',
expected=(expected, digest))
diff --git a/pyramid/session.py b/pyramid/session.py
index a59f9c628..8d0c6c423 100644
--- a/pyramid/session.py
+++ b/pyramid/session.py
@@ -13,6 +13,7 @@ from pyramid.compat import text_
from pyramid.compat import bytes_
from pyramid.compat import native_
from pyramid.interfaces import ISession
+from pyramid.util import strings_differ
def manage_accessed(wrapped):
""" Decorator which causes a cookie to be set when a wrapped
@@ -262,17 +263,10 @@ def signed_deserialize(serialized, secret, hmac=hmac):
sig = hmac.new(bytes_(secret), pickled, sha1).hexdigest()
- if len(sig) != len(input_sig):
- raise ValueError('Wrong signature length')
-
# Avoid timing attacks (see
# http://seb.dbzteam.org/crypto/python-oauth-timing-hmac.pdf)
- invalid_bits = 0
- for a, b in zip(sig, input_sig):
- invalid_bits += a != b
-
- if invalid_bits:
- raise ValueError('Invalid bits in signature')
+ if strings_differ(sig, input_sig):
+ raise ValueError('Invalid signature')
return pickle.loads(pickled)
diff --git a/pyramid/util.py b/pyramid/util.py
index a43b50aef..3eb4b3fed 100644
--- a/pyramid/util.py
+++ b/pyramid/util.py
@@ -208,3 +208,23 @@ class WeakOrderedSet(object):
oid = self._order[-1]
return self._items[oid]()
+def strings_differ(string1, string2):
+ """Check whether two strings differ while avoiding timing attacks.
+
+ This function returns True if the given strings differ and False
+ if they are equal. It's careful not to leak information about *where*
+ they differ as a result of its running time, which can be very important
+ to avoid certain timing-related crypto attacks:
+
+ http://seb.dbzteam.org/crypto/python-oauth-timing-hmac.pdf
+
+ """
+ if len(string1) != len(string2):
+ return True
+
+ invalid_bits = 0
+ for a, b in zip(string1, string2):
+ invalid_bits += a != b
+
+ return invalid_bits != 0
+