Commits

Anonymous committed a4a5abb

Python 3.3 with 2.7 compatibility

  • Participants
  • Parent commits 6b8b639

Comments (0)

Files changed (2)

File django_scrypt/hashers.py

 from django.utils.translation import ugettext_noop as _
 
 import scrypt
-
+import re
+import sys
+PYTHON3 = sys.version_info >= (3, 0)
 
 class ScryptPasswordHasher(BasePasswordHasher):
     """
     p = 1
     buflen = 64
 
+    def base64(self, s):
+        if PYTHON3:
+            import base64
+            return base64.b64encode(s)
+        else:
+            return s.encode('base64')
+
+    def stringify(self, s):
+        if PYTHON3:
+            if type(s) is bytes:
+                return self.stripws(s.decode('utf-8'))
+            else:
+                return self.stripws(s)
+        else:
+            return self.stripws(str(s))
+
+    EMPTY = ''
+    WHITESPACE = re.compile(r'\s+')
+
+    def stripws(self, s):
+        return re.sub(self.WHITESPACE, self.EMPTY, s)
+
+    def liststringify(self, x):
+        return [ self.stringify(i) for i in x ]
+
     def verify(self, password, encoded):
         """
         Checks if the given password is correct
         Returns boolean True or False
 
         """
+        assert encoded
+        encoded = self.stripws(encoded)
         algorithm, salt, Nexp, r, p, buflen, h = encoded.split('$')
         assert algorithm == self.algorithm
         # TODO: buflen is an experimental proposal in py-scrypt
 
         """
         assert password
-        assert salt and '$' not in salt
+        password = self.stringify(password)
+        assert salt
+        salt = self.stringify(salt)
+        assert '$' not in salt
         hashed = [self.algorithm]
         hashed.append(salt)
         if not Nexp:
         hashed.append(str(p))
         hashed.append(str(buflen))
         h = scrypt.hash(password, salt, 2 ** Nexp, r, p)
-        hashed.append(h.encode('base64').strip())
+        hashed.append(self.stringify(self.base64(h)))
         return "$".join(hashed)
 
     def safe_summary(self, encoded):

File tests/test_django_scrypt.py

 
 import django_scrypt
 from django_scrypt.hashers import ScryptPasswordHasher
+import sys
+PYTHON3 = sys.version_info >= (3, 0)
 
 try:
     import scrypt
 
 @skipUnless(scrypt, "Uninstalled scrypt module needed to generate hash")
 class TestScrypt(TestCase):
+    def utf8(self, s):
+        if PYTHON3:
+            return s
+        else:
+            return s.decode('utf-8')
 
     def setUp(self):
         scrypt_hashers = ("django_scrypt.hashers.ScryptPasswordHasher",) + default_hashers
         load_hashers(password_hashers=scrypt_hashers)
         self.password = 'letmein'
-        self.unicode_text = '\xe1\x93\x84\xe1\x93\x87\xe1\x95\x97\xe1\x92\xbb\xe1\x92\xa5\xe1\x90\x85\xe1\x91\xa6'.decode('utf-8')
+        self.unicode_text = self.utf8('\xe1\x93\x84\xe1\x93\x87\xe1\x95\x97\xe1\x92\xbb\xe1\x92\xa5\xe1\x90\x85\xe1\x91\xa6')
         self.bad_password = 'letmeinz'
         self.expected_hash_prefix = "scrypt"
         self.old_format_encoded_hash = "scrypt$FYY1dftUuK0b$16384$8$1$64$/JYOBEED7nMzJgvlqfzDj1JKGVLup0eYLyG39WA2KCywgnB1ubN0uzFYyaEQthINm6ynjjqr+D+U\nw5chi74WVw=="
         with self.assertRaises(Exception) as cm:
             check_password(self.password, self.old_format_encoded_hash)
         self.assertEqual(
-            "hash parameters are wrong (r*p should be < 2**30, and N should be a power of two > 1)",
+            'could not compute hash',
             str(cm.exception))
 
     def test_verify_old_hash_format_fixable(self):