Python 3.6 added a new module called secrets that is designed “to provide an obvious way to reliably generate cryptographically strong pseudo-random values suitable for managing secrets, such as account authentication, tokens, and similar”. Python’s random module was never designed for cryptographic use but for modeling and simulation. Of course, you could always use the urandom() function from Python’s os module:
>>>importos>>>os.urandom(8)'\x9c\xc2WCzS\x95\xc8'
But now that we have the secrets module, we can create our own “cryptographically strong pseudo-random values”. Here’s a simple example:
>>>import secrets >>>importstring>>> characters = string.ascii_letters + string.digits>>> bad_password = ''.join(secrets.choice(characters)for i inrange(8))>>> bad_password 'SRvM54Z1'
In this example, we import the secrets and the string modules. Next we create a string of uppercase letters and integers. Finally we use the secrets module’s choice() method to choose characters randomly to generate a bad password. The reason I am calling this a bad password is because we aren’t using mixed case, numbers and symbols in the password. This is actually a fairly decent one compared with what a lot of people use.
Generating Tokens with secrets
The secrets module also provides several methods of generating tokens. Here are some examples:
>>>: secrets.token_bytes() b'\xd1Od\xe0\xe4\xf8Rn</U\xf4G\xdb\x08\xa8\x85\xeb\xba>\x8cO\xa7XV\x1cb\xd6\x11\xa0\xcaK' >>> secrets.token_bytes(8) b'\xfc,9y\xbe]\x0e\xfb' >>> secrets.token_hex(16)'6cf3baf51c12ebfcbe26d08b6bbe1ac0' >>> secrets.token_urlsafe(16)'5t_jLGlV8yp2Q5tolvBesQ'
The token_bytes function will return a random byte string containing nbytes number of bytes. I didn’t supply a number of bytes in the first example, so Python chose a reasonable number for me. Then I tried calling it again and asking for 8 bytes. The next function we tried is token_hex, which will return a random string in hexadecimal. The last function is token_urlsafe which will return a random URL-safe text string. The text is Base64 encoded too! Note that in practice you should probably use at least 32 bytes for your tokens for them to be secure against a brute-force attack (source).
Wrapping Up
The secrets module is a worthy addition to Python. Frankly I thought something like this should have been added a long time ago. But at least now we have it and now we can safely generate cryptographically strong tokens and passwords. Take some time to check out the documentation for this module as it has a few fun recipes to play around with.
Related Readings
- The secrets module documentation
- What’s new in Python 3.6: secrets module
- PEP 506 — Adding A Secrets Module To The Standard Library