More secure comparison of HMAC strings

To avoid timing attacks. The implementation of SecureCompareStrings is pulled
directly from python 3.4 sources.
This commit is contained in:
Strahinja Val Markovic 2014-05-05 10:35:31 -07:00
parent b56858d2b0
commit ccf0a2ed4d

View File

@ -215,10 +215,33 @@ def SafePopen( *args, **kwargs ):
def ContentHexHmacValid( content, hmac, hmac_secret ):
return hmac == CreateHexHmac( content, hmac_secret )
return SecureCompareStrings( CreateHexHmac( content, hmac_secret ), hmac )
def CreateHexHmac( content, hmac_secret ):
return hmac.new( hmac_secret,
msg = content,
digestmod = hashlib.sha256 ).hexdigest()
# This is the compare_digest function from python 3.4, adapted for 2.7:
# http://hg.python.org/cpython/file/460407f35aa9/Lib/hmac.py#l16
def SecureCompareStrings( a, b ):
"""Returns the equivalent of 'a == b', but avoids content based short
circuiting to reduce the vulnerability to timing attacks."""
# Consistent timing matters more here than data type flexibility
if not ( isinstance( a, str ) and isinstance( b, str ) ):
raise TypeError( "inputs must be str instances" )
# We assume the length of the expected digest is public knowledge,
# thus this early return isn't leaking anything an attacker wouldn't
# already know
if len( a ) != len( b ):
return False
# We assume that integers in the bytes range are all cached,
# thus timing shouldn't vary much due to integer object creation
result = 0
for x, y in zip( a, b ):
result |= ord( x ) ^ ord( y )
return result == 0