web analytics
Skip to main content
Django Python

How to generate a Django password

OK, this is for anyone who needs to manually generate a Django password. I was faced with this problem because I needed to manually insert a new Django user in the database. So, how to take the desired plain text password and to convert it properly so that you can insert it in the “password” field of the auth_user table in the Django database?

To answer this question, I had to take a look at the way Django handles user passwords. Basically, I needed to look at the following Python files from Django repository: utils.py, utils/encoding.py, utils/functional.py.

I’ve grabbed just the functions that I needed and put them together in the following piece of code that you can use.

Just set the “raw_password” variable to the password you want to use. The code uses sha1 as the encryption algorithm. I suppose that it will work for md5 too. Just set the “algorithm” variable to “md5”.

def get_random_string(length=12, allowed_chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'):
	    """
	    Returns a random string of length characters from the set of a-z, A-Z, 0-9
	    for use as a salt.

	    The default length of 12 with the a-z, A-Z, 0-9 character set returns
	    a 71-bit salt. log_2((26+26+10)^12) =~ 71 bits
	    """
	    import random
	    try:
	        random = random.SystemRandom()
	    except NotImplementedError:
	        pass
	    return ''.join([random.choice(allowed_chars) for i in range(length)])

class Promise(object):
	    """
	    This is just a base class for the proxy class created in
	    the closure of the lazy function. It can be used to recognize
	    promises in code.
	    """
	    pass

def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
	    """
	    Returns a bytestring version of 's', encoded as specified in 'encoding'.

	    If strings_only is True, don't convert (some) non-string-like objects.
	    """
	    if strings_only and isinstance(s, (types.NoneType, int)):
	        return s
	    if isinstance(s, Promise):
	        return unicode(s).encode(encoding, errors)
	    elif not isinstance(s, basestring):
	        try:
	            return str(s)
	        except UnicodeEncodeError:
	            if isinstance(s, Exception):
	                # An Exception subclass containing non-ASCII data that doesn't
	                # know how to print itself properly. We shouldn't raise a
	                # further exception.
	                return ' '.join([smart_str(arg, encoding, strings_only,
	                        errors) for arg in s])
	            return unicode(s).encode(encoding, errors)
	    elif isinstance(s, unicode):
	        return s.encode(encoding, errors)
	    elif s and encoding != 'utf-8':
	        return s.decode('utf-8', errors).encode(encoding, errors)
	    else:
		return s		

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').
	    """
	    raw_password, salt = smart_str(raw_password), smart_str(salt)
	    if algorithm == 'crypt':
	        try:
	            import crypt
	        except ImportError:
	            raise ValueError('"crypt" password algorithm not supported in this environment')
	        return crypt.crypt(raw_password, salt)

	    if algorithm == 'md5':
	        return hashlib.md5(salt + raw_password).hexdigest()
	    elif algorithm == 'sha1':
	        return hashlib.sha1(salt + raw_password).hexdigest()
	    raise ValueError("Got unknown password algorithm type in password.")

import hashlib		

algorithm='sha1'
salt=get_random_string()
raw_password='YOUR_PASSWORD_HERE'

raw_password, salt = smart_str(raw_password), smart_str(salt)
hsh = get_hexdigest(algorithm, salt, raw_password)
'%s$%s$%s' % (algorithm, salt, hsh)