1. Daniel Holth
  2. cryptacular

Commits

Daniel Holth  committed 442404e

constant-time comparisons by Patrick Strawderman

  • Participants
  • Parent commits 1be3347
  • Branches default

Comments (0)

Files changed (4)

File cryptacular/bcrypt/__init__.py

View file
 import re
 
 from cryptacular.bcrypt._bcrypt import crypt_rn, crypt_gensalt_rn
+import cryptacular.core
 
 class BCRYPTPasswordManager(object):
 
         rc = crypt_rn(password, encoded)
         if rc is None:
             raise ValueError("_bcrypt.crypt_rn returned None")
-        return rc == encoded
+        return cryptacular.core._cmp(rc, encoded)
 
     def match(self, hash):
         """Return True if hash looks like a BCRYPT password hash."""

File cryptacular/core/__init__.py

View file
 
     def check(self, encoded, password):
         """Return True if 'password' hashes to 'encoded' in this scheme.
-        
+
         Most password schemes require encoded and password to be byte
         strings. The schemes included with this package convert unicode
         'encoded' and 'password' to utf-8 as necessary."""
     def match(self, encoded):
         return True in [m.match(encoded) for m in self._managers]
 
+
+def _cmp(a, b):
+    """Constant-time comparison"""
+    if len(a) != len(b):
+        return False
+
+    result = 0
+    for x, y in zip(a, b):
+        result |= ord(x) ^ ord(y)
+    return result == 0

File cryptacular/crypt/__init__.py

View file
 import crypt
 import base64
 
+import cryptacular.core
+
 OLDCRYPT = ""
 BCRYPT = "$2a$"
 MD5CRYPT = "$1$"
         if not self.match(encoded):
             return False
         rc = self._crypt(password, encoded)
-        return rc == encoded
+        return cryptacular.core._cmp(rc, encoded)
 
     def match(self, hash):
         """Return True if hash starts with our prefix."""

File cryptacular/pbkdf2/__init__.py

View file
 
 import os
 from base64 import urlsafe_b64encode, urlsafe_b64decode
-
+import cryptacular.core
 try: # pragma NO COVERAGE
     import M2Crypto.EVP
     _pbkdf2 = M2Crypto.EVP.pbkdf2
         salt = urlsafe_b64decode(salt)
         keylen = len(urlsafe_b64decode(key))
         hash = self.encode(password, salt, iter, keylen)
-        return hash == encoded
+        return cryptacular.core._cmp(hash, encoded)
 
     def match(self, encoded):
         """True if encoded appears to match this scheme."""