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.
| | |
| | | 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): |
| | |
| | | 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)) |
| | | |
| | |
| | | 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 |
| | |
| | | |
| | | 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) |
| | | |
| | |
| | | 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 |
| | | |