SECRET_KEYs on the command line using this “one-liner” (django not required)
Django is a Python web framework with a lot of nice features including an exceptional ORM and high quality documentation. Most of my experience with django has been deploying and debugging other people’s projects - during the course of which I often want to regenerate the
SECRET_KEY that underpins most of the security of every deployment.
The django settings docs describe the
A secret key for a particular Django installation. This is used to provide cryptographic signing, and should be set to a unique, unpredictable value.
django-admin startprojectautomatically adds a randomly-generated
SECRET_KEYto each new project.
The secret key is used for:
- All sessions if you are using any other session backend than django.contrib.sessions.backends.cache, or are using the default get_session_auth_hash().
- All messages if you are using CookieStorage or FallbackStorage.
- All PasswordResetView tokens.
- Any usage of cryptographic signing, unless a different key is provided.
If you rotate your secret key, all of the above will be invalidated. Secret keys are not used for passwords of users and key rotation will not affect them.
To figure out how to generate new keys let’s take a look at how django generates the key during project creation.
As of this writing, the core/management/utils module source code contains 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)
That’s pretty easy to read – we need 50 characters of
0-9, and the US english keyboard layout’s top-row symbols:
). (That looks like kind of an unusual character set for security use – I suspect base64 would probably be a better option.)
Now that we know the requirements we can use that to craft the following one-liner for generating django secret keys on the command-line:
python -c 'import random; choice=random.SystemRandom().choice; print("".join([choice("abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)") for _ in range(50)]));'