Python Simplified

Python secrets module for strong random number and token generation

Python secrets module

Introduction

Do you know Python has a built-in module called secrets that can be used to generate cryptographically strong passwords, tokens, and other related secrets? The secrets module was first introduced in Python 3.6 (PEP 506). 

Before the introduction of the secrets module into Python, the random module was used by the majority of developers for generating passwords, tokens, etc. But the random numbers generated by the random module are pseudo-random numbers and are not cryptographically secure. Hence, the secrets module was introduced into Python 3.6 onwards.

You will see the below warning on the random module official documentation page — “The pseudo-random generators of this module should not be used for security purposes. For security or cryptographic uses, see the secrets module.”

Secrets

The secrets module functions can be divided into two sections — generating random numbers and generating tokens.

Generating random numbers

1) secrets.choice(sequence)  – returns a random element from a non-empty sequence. The below two examples returns a random character in the rage A-Za-z and a random number in the range 0–10.

				
					>>> secrets.choice(seq=string.ascii_letters)
'B'

>>> secrets.choice(seq=range(10))
2
				
			

2) secrets.randbelow(n) — returns a random integer in the range 0-n (excluding n). The below example returns a random integer in the range 0–10.

				
					>>> secrets.randbelow(exclusive_upper_bound=10)
5
				
			

3) secrets.randbits(k) — returns a random integer with k-bits. The below example return a random integer formed with 8-bits.

  • If k=4 then the random integer will be from 0 to 15.
  • if k=8 then the random integer will be from 0 to 255.
  • If k=16 then the random integer will be from 0 to 65,535, and so on.
				
					>>> secrets.randbits(k=8)
46
				
			

4) secrets.SystemRandom() — Each operating system comes up with a source to generate secure and strong random numbers. The SystemRandom is a class available in the random module which in turn uses os.urandom() function for generating the secure random numbers.

As highlighted earlier, before the introduction of the secrets module, SystemRandom class was used to generate secure and cryptographically strong random numbers/tokens. In fact, you can access all the random module functions/methods using the SystemRandom object. 

As you can see from the below code, you are able to access random module functions using SystemRandom class. You can try other functions/methods available in the random module.

				
					>>> import secrets
>>> sys_random = secrets.SystemRandom()

>>> sys_random.choice(seq=range(10))
6

>>> sys_random.getrandbits(k=8)
88

>>> sys_random.randrange(1, 100)
45

>>> sys_random.sample(range(100), 5)
[85, 73, 31, 88, 48]
				
			

Generating tokens

The secrets module also provides functions that can be used for applications such as password reset, hard-to-guess URLs, etc. as discussed below.

1) secrets.token_bytes —returns secure random byte strings with the bytes specified in nbytes parameter. If nbytes is None or not supplied, a reasonable default is used.

The below examples return 8 and 16 token bytes as specified in the parameter.

				
					>>> secrets.token_bytes(8)
b'>k\t\xbcO\x8dg\xd6'

>>> secrets.token_bytes(16)
b'\xe81\xedT\xfcOP\xe9\x9e\x87\xa4\xec\xa0\xffH9'
				
			

2) secrets.token_hex — returns secure random byte strings in hexadecimal format with the bytes specified in nbytes parameter. If nbytes is None or not supplied, a reasonable default is used.

The below examples return 8 and 16 token bytes in hexa-decimal format as specified in the parameter.

				
					>>> secrets.token_hex(8)
'796d446a4dcbe000'

>>> secrets.token_hex(16)
'6e8b324b58f0d94d5f6440b90c59d350'
				
			

3) secrets.token_urlsafe — returns a secure random URL-safe text string with the bytes specified in nbytes parameter.

The below examples return 8 and 16 bytes string as specified in the parameter.

				
					>>> secrets.token_urlsafe(8)
'GLyhe4JD72g'

>>> secrets.token_urlsafe(16)
'kJkUOJIUZRAYkEgFR6X52w'
				
			

Examples

Based on the knowledge we gained from the above functions, we can now create cryptographically strong passwords, OTP, tokens, etc. Let’s look at a few use cases.

(1) Generate 8 character alpha-numeric password

				
					>>> import string
>>> import secrets

>>> alphabet = string.ascii_letters + string.digits
>>> password = ''.join(secrets.choice(alphabet) for i in range(8))
>>> password
'ubHLOZY1'
				
			

(2) Generate 6 digit numeric OTP

				
					>>> import string
>>> import secrets

>>> numbers = string.digits
>>> OTP = ''.join(secrets.choice(numbers) for i in range(8))
>>> OTP
'904447'
				
			

(3) Generate a 10-character password with at least one upper-case, one lower-case, one digit, one special character, and at least 5 alphabets.

				
					>>> import string
>>> import secrets

>>> alphabet = string.ascii_letters + string.digits + string.punctuation
>>> while True:
...     password = ''.join(secrets.choice(alphabet) for i in range(10))
...     if (any(c.islower() for c in password)
...             and any(c.isupper() for c in password)
...             and any(c.islower() for c in password)
...             and any(c.isdigit() for c in password)
...             and any(c in string.punctuation for c in password)
...             and sum(c.isalpha() for c in password) >= 5):
...         break

>>> password
"hMyo>'A5<="
				
			

(4) Generate temporary URL secure token for password reset

Assume that you may have forgotten the password to a website. When you request for a password reset, after the authentication of user-id, email-id, or other authentication methods, you will be provided with a secure URL for a password reset. Below is the sample code using token_urlsafe().

				
					>>> print("Password Reset link:")
>>> SecureURL = "https://mysite.com/user/chetanambi/passwordreset="
>>> SecureURL += secrets.token_urlsafe(32)

>>> print(SecureURL)
Password Reset link:
https://mysite.com/user/chetanambi/passwordreset=urtFK4CeJvJ0f7nVbPAAZw
				
			

PRNG Vs CSPRNG

PRNG stands for Pseudo-Random Number Generator and CSPRNG means Cryptographically Strong Pseudo-Random Number Generator.

The random numbers generated by any software are pseudo-random in nature as they come from some distribution and can be predicted if the seed is known. On other hand, truly random numbers use some external source that is unpredictable for random number generation. The CSPRNG in Python is a true random number generator as it uses OS as random number generator source.

Conclusion

In this article, you have been introduced to the Python secrets module. The secrets module is used to generate cryptographically strong and secure passwords, OTPs, tokens, and other related secrets. The random module in Python can also be used to generate random numbers but it is not secure. I hope that the above examples we discussed above will help you get started using the secrets module.

References

Share on facebook
Share on twitter
Share on linkedin
Share on whatsapp
Share on email
Chetan Ambi

Chetan Ambi

A Software Engineer & Team Lead with over 10+ years of IT experience, a Technical Blogger with a passion for cutting edge technology. Currently working in the field of Python, Machine Learning & Data Science. Chetan Ambi holds a Bachelor of Engineering Degree in Computer Science.
Scroll to Top