Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Merge pull request #1644 from PaulMcMillan/bump_hash_iterations

Increase default PBKDF2 iterations
  • Loading branch information...
commit f8f47718abb4c93ef00f93dde42101a8dd17a700 2 parents 2c5c422 + a075e2a
Paul McMillan authored September 19, 2013
4  django/contrib/auth/hashers.py
@@ -231,12 +231,12 @@ class PBKDF2PasswordHasher(BasePasswordHasher):
231 231
     """
232 232
     Secure password hashing using the PBKDF2 algorithm (recommended)
233 233
 
234  
-    Configured to use PBKDF2 + HMAC + SHA256 with 10000 iterations.
  234
+    Configured to use PBKDF2 + HMAC + SHA256 with 12000 iterations.
235 235
     The result is a 64 byte binary string.  Iterations may be changed
236 236
     safely but you must rename the algorithm if you change SHA256.
237 237
     """
238 238
     algorithm = "pbkdf2_sha256"
239  
-    iterations = 10000
  239
+    iterations = 12000
240 240
     digest = hashlib.sha256
241 241
 
242 242
     @password_max_length(MAXIMUM_PASSWORD_LENGTH)
10  django/contrib/auth/tests/test_hashers.py
@@ -52,7 +52,7 @@ def test_simple(self):
52 52
     def test_pkbdf2(self):
53 53
         encoded = make_password('lètmein', 'seasalt', 'pbkdf2_sha256')
54 54
         self.assertEqual(encoded,
55  
-            'pbkdf2_sha256$10000$seasalt$CWWFdHOWwPnki7HvkcqN9iA2T3KLW1cf2uZ5kvArtVY=')
  55
+            'pbkdf2_sha256$12000$seasalt$Ybw8zsFxqja97tY/o6G+Fy1ksY4U/Hw3DRrGED6Up4s=')
56 56
         self.assertTrue(is_password_usable(encoded))
57 57
         self.assertTrue(check_password('lètmein', encoded))
58 58
         self.assertFalse(check_password('lètmeinz', encoded))
@@ -284,16 +284,16 @@ def encode(s, password, salt):
284 284
 
285 285
     def test_low_level_pkbdf2(self):
286 286
         hasher = PBKDF2PasswordHasher()
287  
-        encoded = hasher.encode('lètmein', 'seasalt')
  287
+        encoded = hasher.encode('lètmein', 'seasalt2')
288 288
         self.assertEqual(encoded,
289  
-            'pbkdf2_sha256$10000$seasalt$CWWFdHOWwPnki7HvkcqN9iA2T3KLW1cf2uZ5kvArtVY=')
  289
+            'pbkdf2_sha256$12000$seasalt2$hlDLKsxgkgb1aeOppkM5atCYw5rPzAjCNQZ4NYyUROw=')
290 290
         self.assertTrue(hasher.verify('lètmein', encoded))
291 291
 
292 292
     def test_low_level_pbkdf2_sha1(self):
293 293
         hasher = PBKDF2SHA1PasswordHasher()
294  
-        encoded = hasher.encode('lètmein', 'seasalt')
  294
+        encoded = hasher.encode('lètmein', 'seasalt2')
295 295
         self.assertEqual(encoded,
296  
-            'pbkdf2_sha1$10000$seasalt$oAfF6vgs95ncksAhGXOWf4Okq7o=')
  296
+            'pbkdf2_sha1$12000$seasalt2$JeMRVfjjgtWw3/HzlnlfqBnQ6CA=')
297 297
         self.assertTrue(hasher.verify('lètmein', encoded))
298 298
 
299 299
     def test_upgrade(self):
11  django/utils/crypto.py
@@ -139,11 +139,12 @@ def pbkdf2(password, salt, iterations, dklen=0, digest=None):
139 139
 
140 140
     HMAC+SHA256 is used as the default pseudo random function.
141 141
 
142  
-    Right now 10,000 iterations is the recommended default which takes
143  
-    100ms on a 2.2Ghz Core 2 Duo.  This is probably the bare minimum
144  
-    for security given 1000 iterations was recommended in 2001. This
145  
-    code is very well optimized for CPython and is only four times
146  
-    slower than openssl's implementation.
  142
+    As of 2011, 10,000 iterations was the recommended default which
  143
+    took 100ms on a 2.2Ghz Core 2 Duo. This is probably the bare
  144
+    minimum for security given 1000 iterations was recommended in
  145
+    2001. This code is very well optimized for CPython and is only
  146
+    four times slower than openssl's implementation. Look in
  147
+    django.contrib.auth.hashers for the present default.
147 148
     """
148 149
     assert iterations > 0
149 150
     if not digest:
7  docs/internals/howto-release-django.txt
@@ -89,6 +89,13 @@ any time leading up to the actual release:
89 89
    key you'll use for the release, and should include patches for each issue
90 90
    being fixed.
91 91
 
  92
+#. If this is a major release, make sure the tests pass, then increase
  93
+   the default PBKDF2 iterations in
  94
+   ``django.contrib.auth.hashers.PBKDF2PasswordHasher`` by about 10%
  95
+   (pick a round number). Run the tests, and update the 3 failing
  96
+   hasher tests with the new values. Make sure this gets noted in the
  97
+   release notes (see release notes on 1.6 for an example).
  98
+
92 99
 #. As the release approaches, watch Trac to make sure no release blockers
93 100
    are left for the upcoming release.
94 101
 
7  docs/releases/1.6.txt
@@ -365,6 +365,13 @@ Minor features
365 365
   a list (except on SQLite). This has long been possible (but not officially
366 366
   supported) on MySQL and PostgreSQL, and is now also available on Oracle.
367 367
 
  368
+* The default iteration count for the PBKDF2 password hasher has been
  369
+  increased by 20%. This backwards compatible change will not affect
  370
+  existing passwords or users who have subclassed
  371
+  `django.contrib.auth.hashers.PBKDF2PasswordHasher`` to change the
  372
+  default value.
  373
+
  374
+
368 375
 Backwards incompatible changes in 1.6
369 376
 =====================================
370 377
 

0 notes on commit f8f4771

Please sign in to comment.
Something went wrong with that request. Please try again.