Skip to content

Commit

Permalink
Use constant time string comparisons for auth.
Browse files Browse the repository at this point in the history
Fix bug 942644.

Use constant time string comparisons when doing authentication to help
guard against timing attacks.

Change-Id: I88c4c5cd9edd9e5d60db07b6ae2638b74a2a2e17
  • Loading branch information
russellb committed Feb 28, 2012
1 parent 85ee3aa commit 1f0798f
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 2 deletions.
5 changes: 3 additions & 2 deletions swift/common/middleware/formpost.py
Expand Up @@ -110,7 +110,7 @@
from time import time
from urllib import quote, unquote

from swift.common.utils import get_logger
from swift.common.utils import get_logger, strcmp_const_time


#: The size of data to read from the form at any given time.
Expand Down Expand Up @@ -442,7 +442,8 @@ def _perform_subrequest(self, env, start_response, attributes, fp, key):
attributes.get('expires') or '0'
)
sig = hmac.new(key, hmac_body, sha1).hexdigest()
if sig != (attributes.get('signature') or 'invalid'):
if not strcmp_const_time(sig,(attributes.get('signature') or
'invalid')):
return '401 Unauthorized', 'invalid signature'
subenv['swift.authorize'] = lambda req: None
subenv['swift.authorize_override'] = True
Expand Down
20 changes: 20 additions & 0 deletions swift/common/utils.py
Expand Up @@ -1117,3 +1117,23 @@ def listdir(path):
if err.errno != errno.ENOENT:
raise
return []


def strcmp_const_time(s1, s2):
"""Constant-time string comparison.
:params s1: the first string
:params s2: the second string
:return: True if the strings are equal.
This function takes two strings and compares them. It is intended to be
used when doing a comparison for authentication purposes to help guard
against timing attacks.
"""
if len(s1) != len(s2):
return False
result = 0
for (a, b) in zip(s1, s2):
result |= ord(a) ^ ord(b)
return result == 0
5 changes: 5 additions & 0 deletions test/unit/common/test_utils.py
Expand Up @@ -850,6 +850,11 @@ def test_TRUE_VALUES(self):
for v in utils.TRUE_VALUES:
self.assertEquals(v, v.lower())

def test_strcmp_const_time(self):
self.assertTrue(utils.strcmp_const_time('abc123', 'abc123'))
self.assertFalse(utils.strcmp_const_time('a', 'aaaaa'))
self.assertFalse(utils.strcmp_const_time('ABC123', 'abc123'))


if __name__ == '__main__':
unittest.main()

0 comments on commit 1f0798f

Please sign in to comment.