Frank Smit avatar Frank Smit committed 02fb82b

Fixed some errors and added a unit test.

Comments (0)

Files changed (2)

cryptacular/bcrypt/__init__.py

 
 class BCRYPTPasswordManager(object):
 
-    SCHEME = 'BCRYPT'
-    PREFIX = '$2a$'
-    ROUNDS = 10
+    _scheme = 'BCRYPT'
+    _prefix = '$2a$'
+    _rounds = 10
 
     _bcrypt_syntax = re.compile('\$2a\$[0-9]{2}\$[./A-Za-z0-9]{53}')
 
-    def encode(self, password, rounds=None):
+    def encode(self, text, rounds=None):
         '''Hash a password using bcrypt.
 
         Note: only the first 72 characters of password are significant.
 
         return encoded
 
-    def check(self, encoded, password):
+    def check(self, encoded, text):
         '''Check a bcrypt password hash against a password.
         '''
-        if not self.valid(encoded):
+        if not self.match(encoded):
             return False
 
         encoded_text = crypt_rn(check_unicode(text), encoded)
     def match(self, hash):
         '''Return True if hash looks like a BCRYPT password hash.
         '''
-        return self._bcrypt_syntax.match(encoded) is not None
+        return self._bcrypt_syntax.match(hash) is not None
 

tests/test_bcrypt.py

+import unittest
+from cryptacular.bcrypt import BCRYPTPasswordManager
+
+
+try:
+    unicode
+except NameError:
+    unicode = str
+
+
+class TestBcrypt(unittest.TestCase):
+
+    snowpass = unicode('hashy the \N{SNOWMAN}')
+
+    def setUp(self):
+        self.bcrypt = BCRYPTPasswordManager()
+
+    def test_none_1(self):
+        self.assertRaises(TypeError, self.bcrypt.encode, None)
+
+    def test_none_2(self):
+        self.assertRaises(TypeError, self.bcrypt.check, None, 'xyzzy')
+
+    def test_none_3(self):
+        hash = self.bcrypt.encode('xyzzy')
+        self.assertRaises(TypeError, self.bcrypt.check, hash, None)
+
+    def test_badhash(self):
+        self.assertFalse(
+            self.bcrypt.check(
+                '$p5k2$400$ZxK4ZBJCfQg=$kBpklVI9kA13kP32HMZL0rloQ1M=',
+            self.snowpass))
+
+    def test_shorthash(self):
+        def match(hash):
+            return True
+        bcrypt = BCRYPTPasswordManager()
+        bcrypt.match = match
+        short_hash = bcrypt.encode(self.snowpass)[:28]
+        self.assertRaises(ValueError, bcrypt.check, short_hash, self.snowpass)
+
+    def test_too_few_rounds(self):
+        self.assertRaises(ValueError, self.bcrypt.encode, self.snowpass, rounds=1)
+
+    def test_too_many_rounds(self):
+        self.assertRaises(ValueError, self.bcrypt.encode,
+            self.snowpass, rounds=100)
+
+    def test_emptypass(self):
+        self.bcrypt.encode('')
+
+    def test_valid_hash_1(self):
+        hash = self.bcrypt.encode(self.snowpass)
+        self.assertTrue(self.bcrypt.match(hash))
+        self.assertTrue(self.bcrypt.check(hash, self.snowpass))
+        self.assertEqual(len(hash), 60)
+
+    def test_valid_hash_2(self):
+        password = "xyzzy"
+        hash = self.bcrypt.encode(password)
+        self.assertTrue(self.bcrypt.check(hash, password))
+        self.assertTrue(self.bcrypt.check(unicode(hash), password))
+        self.assertFalse(self.bcrypt.check(password, password))
+        self.assertNotEqual(self.bcrypt.encode(password),
+            self.bcrypt.encode(password))
+        hash = self.bcrypt.encode(password, rounds=4)
+        self.assertTrue(self.bcrypt.check(hash, password))
+
+
+if __name__ == '__main__':
+    unittest.main()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.