Index: django/conf/global_settings.py
===================================================================
--- django/conf/global_settings.py	(revision 6423)
+++ django/conf/global_settings.py	(working copy)
@@ -326,6 +326,8 @@
 
 AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',)
 
+AUTH_CRYPTO_ALGORITHM = 'sha1'
+
 LOGIN_URL = '/accounts/login/'
 
 LOGOUT_URL = '/accounts/logout/'
Index: django/contrib/auth/models.py
===================================================================
--- django/contrib/auth/models.py	(revision 6423)
+++ django/contrib/auth/models.py	(working copy)
@@ -1,3 +1,4 @@
+from django.conf import settings
 from django.contrib import auth
 from django.core import validators
 from django.core.exceptions import ImproperlyConfigured
@@ -8,8 +9,10 @@
 from django.utils.translation import ugettext_lazy as _
 import datetime
 import urllib
+import base64
 
 UNUSABLE_PASSWORD = '!' # This will never be a valid hash
+SALT_CHOICES = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
 
 try:
     set
@@ -19,7 +22,7 @@
 def get_hexdigest(algorithm, salt, raw_password):
     """
     Returns a string of the hexdigest of the given plaintext password and salt
-    using the given algorithm ('md5', 'sha1' or 'crypt').
+    using the given algorithm ('md5', 'sha1', 'sha2', 'sha256', or 'crypt').
     """
     raw_password, salt = smart_str(raw_password), smart_str(salt)
     if algorithm == 'crypt':
@@ -39,11 +42,15 @@
         elif algorithm == 'sha1':
             import sha
             return sha.new(salt + raw_password).hexdigest()
+        else:
+            raise ValueError("Got unsupported password algorithm type in password.")
     else:
         if algorithm == 'md5':
             return hashlib.md5(salt + raw_password).hexdigest()
         elif algorithm == 'sha1':
             return hashlib.sha1(salt + raw_password).hexdigest()
+        elif algorithm == 'sha256' or algorithm == 'sha2':
+            return hashlib.sha256(salt + raw_password).hexdigest()
     raise ValueError("Got unknown password algorithm type in password.")
 
 def check_password(raw_password, enc_password):
@@ -182,8 +189,8 @@
 
     def set_password(self, raw_password):
         import random
-        algo = 'sha1'
-        salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5]
+        algo = settings.AUTH_CRYPTO_ALGORITHM
+        salt = ''.join([random.choice(SALT_CHOICES) for n in range(10)])
         hsh = get_hexdigest(algo, salt, raw_password)
         self.password = '%s$%s$%s' % (algo, salt, hsh)
 
@@ -196,12 +203,12 @@
         # algorithm or salt.
         if '$' not in self.password:
             is_correct = (self.password == get_hexdigest('md5', '', raw_password))
-            if is_correct:
-                # Convert the password to the new, more secure format.
-                self.set_password(raw_password)
-                self.save()
-            return is_correct
-        return check_password(raw_password, self.password)
+        else:
+            is_correct = check_password(raw_password, self.password)
+        if is_correct:
+            # Convert the password to the new, more secure format.
+            self.convert_password(raw_password)
+        return is_correct
 
     def set_unusable_password(self):
         # Sets a value that will never be a valid hash
@@ -210,6 +217,18 @@
     def has_usable_password(self):
         return self.password != UNUSABLE_PASSWORD
 
+    def convert_password(self, raw_password):
+        """
+        Convert, in place, the user's password (raw_password). This will
+        convert from any earlier version of password form, or to a new
+        crypto algorithm as set in AUTH_CRYPTO_ALGORITHM. This will also
+        expand the potential size of the salt.
+        """
+        algo, salt, password = self.password.split('$')
+        if algo != settings.AUTH_CRYPTO_ALGORITHM or len(salt) < 10:
+            self.set_password(raw_password)
+            self.save()
+
     def get_group_permissions(self):
         """
         Returns a list of permission strings that this user has through
Index: docs/settings.txt
===================================================================
--- docs/settings.txt	(revision 6423)
+++ docs/settings.txt	(working copy)
@@ -225,6 +225,15 @@
 ``CommonMiddleware`` is installed (see the `middleware docs`_). See also
 ``PREPEND_WWW``.
 
+AUTH_CRYPTO_ALGORITHM
+---------------------
+
+Default: ``sha1``
+
+Determines the cryptograph algorithm to use in storing user passwords in the
+database. Available options are ``sha1``, ``sha2``, ``sha256``, ``md5`` and
+``crypto``. Note that ``sha2`` and ``sha256`` are synonyms.
+
 CACHE_BACKEND
 -------------
 
Index: docs/authentication.txt
===================================================================
--- docs/authentication.txt	(revision 6423)
+++ docs/authentication.txt	(working copy)
@@ -218,12 +218,13 @@
 
 That's hashtype, salt and hash, separated by the dollar-sign character.
 
-Hashtype is either ``sha1`` (default), ``md5`` or ``crypt`` -- the algorithm
-used to perform a one-way hash of the password. Salt is a random string used
-to salt the raw password to create the hash. Note that the ``crypt`` method is
-only supported on platforms that have the standard Python ``crypt`` module
-available, and ``crypt`` support is only available in the Django development
-version.
+Hashtype is either ``sha1`` (default), ``sha2``, ``sha256``, ``md5`` or
+``crypt`` -- the algorithm used, based on the `AUTH_CRYPTO_ALGORITHM`_
+setting, to perform a one-way hash of the password. Salt is a random string
+used to salt the raw password to create the hash. Note that the ``crypt``
+method is only supported on platforms that have the standard Python ``crypt``
+module available, and ``crypt`` support is only available in the Django
+development version.
 
 For example::
 
@@ -237,6 +238,8 @@
 converted automatically to the new style the first time ``User.check_password()``
 works correctly for a given user.
 
+.. _AUTH_CRYPTO_ALGORITHM: ../settings/#auth-crypto-algorithm
+
 Anonymous users
 ---------------
 
