Django: Generate new Secret Key

Created: 29.06.2022 | Last edited: 19.07.2022

TL;DR

Run this command in your terminal:

python3 -c "import secrets;print(''.join(secrets.choice('abcdefghijklmnopqrstuvwxyz0123456789%^&*(-_=+)') for i in range(50)))"

and set the resulting string as your new secret key in your settings file.

What is the Django secret key even used for?

Ever wondered what the SECRET_KEY setting will do for you? It will protect your data as well as your users data, like serialized json data or password reset requests, by cryptographically signing them and generating unique salt for hash functions. Or to simplify: it is used to secure sessions, data, and passwords across all apps that come with django (like the django admin) as well as all apps who might access such features.

How does Django generate secret keys?

If we look at djangos source code we can find the following function:

def get_random_secret_key():
    """
    Return a 50 character random string usable as a SECRET_KEY setting value.
    """
    chars = "abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)"
    return get_random_string(50, chars)

Now we just need to explore what get_random_string actually does:

def get_random_string(length, allowed_chars=RANDOM_STRING_CHARS):
    """
    Return a securely generated random string.

    The bit length of the returned value can be calculated with the formula:
        log_2(len(allowed_chars)^length)

    For example, with default `allowed_chars` (26+26+10), this gives:
      * length: 12, bit length =~ 71 bits
      * length: 22, bit length =~ 131 bits
    """
    return "".join(secrets.choice(allowed_chars) for i in range(length))

If you wonder "what is secrets.choice ?" then well...there is a fairly new module in python introduced in version 3.6 called secrets with this function returning a random character from a given sequence.

For now all we need to know: a secret key is a 50 character long string consisting of following letters: a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 ! @ # $ % ^ & * ( - _ = + ).

Generating our own secret keys

We could simplify what django is doing like this:

import secrets

def get_new_django_secret_key():
    return "".join(secrets.choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50))

our_new_secret_key = get_new_django_secret_key()

If we don't want a script and just run it from the command line here is a quick one-liner:

python3 -c "import secrets;print(''.join(secrets.choice('abcdefghijklmnopqrstuvwxyz0123456789%^&*(-_=+)') for i in range(50)))"

Besides this, with the knowledge we have now you could also safely use any function that you prefer to generate the secret key (or write your own) as long as you can fill up 50 characters and only use the allowed characters.