Source

django-scrypt / tests / test_django_scrypt.py

Diff from to

tests/test_django_scrypt.py

         self.password = 'letmein'
         self.bad_password = 'letmeinz'
         self.expected_hash_prefix = "scrypt"
+        self.old_format_encoded_hash = "scrypt$FYY1dftUuK0b$16384$8$1$64$/JYOBEED7nMzJgvlqfzDj1JKGVLup0eYLyG39WA2KCywgnB1ubN0uzFYyaEQthINm6ynjjqr+D+U\nw5chi74WVw=="
+        self.old_format_fix_encoded_hash = "scrypt$FYY1dftUuK0b$14$8$1$64$/JYOBEED7nMzJgvlqfzDj1JKGVLup0eYLyG39WA2KCywgnB1ubN0uzFYyaEQthINm6ynjjqr+D+U\nw5chi74WVw=="
+        self.encoded_hash = "scrypt$gwQg9TZ3eyub$14$8$1$64$lQhi3+c0xkYDUj35BvS6jVTlHRAH/RS4nkpd1tKMc0r9PcFyjCjPj1k9/CkSCRvcTvHiWfFYpHfB\nZDCHMNIeHA=="
 
-    def test_verify_bad_passwords_fail(self):
-        """Test verify method causes failure on mismatched passwords"""
-        encoded = make_password(self.password)
-        self.assertFalse(check_password(self.bad_password, encoded))
-
-    def test_verify_passwords_match(self):
-        """Test verify method functions via check_password"""
-        encoded = make_password(self.password)
-        self.assertTrue(check_password(self.password, encoded))
-
-    def test_encoder_hash_less_than_128_characters(self):
+    def test_default_encoder_hash_less_than_128_characters(self):
         """Test that returned encoded hash is less than db limit of 128 characters"""
         encoded = make_password(self.password)
         self.assertTrue(len(encoded) < 128)
         self.assertTrue(d[_('buflen')].isdigit())
         self.assertTrue(len(d[_('hash')]))
 
+    def test_verify_bad_passwords_fail(self):
+        """Test verify method causes failure on mismatched passwords"""
+        encoded = make_password(self.password)
+        self.assertFalse(check_password(self.bad_password, encoded))
+
+    def test_verify_passwords_match(self):
+        """Test verify method functions via check_password"""
+        encoded = make_password(self.password)
+        self.assertTrue(check_password(self.password, encoded))
+
+    def test_verify_default_hash_format_usable(self):
+        """Test encoded format passes good password"""
+        self.assertTrue(check_password(self.password, self.encoded_hash))
+
+    def test_verify_old_hash_format_raises_error(self):
+        """Test that old encoded format raises error"""
+        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)",
+            str(cm.exception))
+
+    def test_verify_old_hash_format_fixable(self):
+        """Test deprecated encoded format can be fixed by swapping Nexp for N
+        
+        Specifically, replace 16384 with 14 at position 3 of the encoded hash
+        """
+        self.assertTrue(check_password(self.password, self.old_format_fix_encoded_hash))
+
     def test_class_algorithm_string_matches_expected(self):
         """Test django_scrypt algorithm string matches expected value 'scrypt'"""
         self.assertEqual(ScryptPasswordHasher.algorithm, self.expected_hash_prefix)