Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Avoid timing attacks in AuthTktAutenticationPolicy

This factors out the timing-invariant string comparison code from
session.py and re-uses it for signature checking in AuthTkt code.
  • Loading branch information...
commit c8c9bc80621bea468d2dbd440255b9f0b7baeb4e 1 parent 4791d7b
Ryan Kelly rfk authored mcdonc committed
Showing with 28 additions and 10 deletions.
  1. +5 −1 pyramid/authentication.py
  2. +3 −9 pyramid/session.py
  3. +20 −0 pyramid/util.py
6 pyramid/authentication.py
View
@@ -14,6 +14,8 @@
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):
@@ -486,7 +488,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))
12 pyramid/session.py
View
@@ -14,6 +14,7 @@
from zope.interface import implements
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
@@ -261,17 +262,10 @@ def signed_deserialize(serialized, secret, hmac=hmac):
sig = hmac.new(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)
20 pyramid/util.py
View
@@ -207,3 +207,23 @@ def last(self):
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
+
Please sign in to comment.
Something went wrong with that request. Please try again.