Create and Manage Cryptographically Strong Tokens with Python for Better Web Application Security

Secret key management is a crucial aspect of a software engineer's daily routine. In this article, you will explore how to create and manage cryptographically secure keys in Python using the popular Pypi cryptography module. You will also learn the importance of securely storing these keys to ensure maximum protection of sensitive data in your web applications and software.

Prerequisites

You must install Python on your machine if you don't have it installed. It’s the only needed external requirement. You can install Python from their official downloads page. It’s recommended to install the latest version of Python for this tutorial.

To follow up with this tutorial, you are required to have some knowledge about writing simple Python programs. All the packages that will be discussed are from the Python standard library or Pypi package manager.

Secured Symmetrical Encryption Keys

When it comes to encryption and decryption in Python, the Pypi cryptography module is a popular choice. One of the easiest and most secure ways to implement symmetric cryptography using this module is through Fernet symmetrical encryption. However, to use Fernet keys for symmetric encryption, they must be generated and stored securely.

Let's dive in.

Start by creating a new Python project and set up your virtual environment to separate your project dependencies from your global dependencies.

python -m venv venv
# or
python3 -m venv venv

The Python command above is possible with Python3. If you have any errors setting this up, check out Python's official venv documentation to learn about creating a virtual environment.

  • Activate the created environment
# Windows: cmd.exe
venv\Script\activate

# Linux: bash or Mac: zsh
source venv/bin/activate

Depending on your shell, the command for activating your virtual environment will be different. Check this reference for the command that will work for your shell.

  • Now you need to install cryptography
pip install cryptography

If you encounter any installation issues, you can check out its installation guide.

Enter the Python shell and run the following commands to generate the key.

>>> from cryptography.fernet import Fernet
>>> key = Fernet.generate_key()
b'RAuFlYBGswBmBOccV13UNYXxJTi19LCGhUOLZOi6oFY='

The value RAuFlYBGswBmBOccV13UNYXxJTi19LCGhUOLZOi6oFY= in the byte string is the important key. It's stored like that because that's what the cryptography library likes to work with. So, if you generate a new key in the future, you need to convert it to bytes before passing it to any hash function.

Is Fernet.generate_key() cryptographically secure?

The answer is a resounding YES!

The implementation of Fernet.generate_key method uses the function os.urandom, which has more sufficient randomness than the random function from the built-in random module.

Why? It's because os.urandom cannot be seeded like random and draws its source of entropy from many unpredictable sources, making it more random. For more understanding, you can check this StackOverflow answer.

Now you can use your securely generated key to encrypt and decrypt data.

# Initialize a Fernet object
>>> f = Fernet(key)

# Generate a cryptographically secure and url-safe fernet token
>>> token = f.encrypt(b"Hashnode Neptune is the best")
>>> print(token)
b'gAAAAABkDv-R51WpztocZoMMat3UyKg8jz6KgCQgCq4g9SU36OF7kiPhqQwjLXPT-39lbb5cL-MlUWSmoDLKXlkOZo2Od_Icp_6jPFLDgF32f2r9agrRr50='

There you have it. You have generated a secure token that you can use to ensure your data security in your projects.

If you don't want to use the generate_key function to create your Fernet tokens. You can use this resource to generate a more secure and strong token using the PBKDF2HMAC algorithm.

Securely Managing Your Secret Keys

To ensure complete security, you must store your keys safely. Never share with anyone.

One easy way to do this is to use Pypi decouple.

  • Let's start by installing it in our environment.
pip install python-decouple
  • Create a file .env in your project directory. Add the key generated earlier to the file.
SECRET_KEY="RAuFlYBGswBmBOccV13UNYXxJTi19LCGhUOLZOi6oFY="

Save the file.

  • Create a new Python program, main.py, in your project directory. Then paste the code added below into the file.
from decouple import config

SECRET_KEY = config('SECRET_KEY')

print(SECRET_KEY)

Run the main.py python program.

python main.py

The secret key stored in the environment file would be displayed. Decouple is a project used to store the environment and secret keys. You can read more at Pypi Decouple.

What makes this approach better than using an operating system environment? Because it makes it easier to share secrets when collaborating with others. They only need to clone the project and copy the .env file.

Also, it eliminates the collision of similar keys on multiple projects on the same machine. As a bonus, you can create a file env.example, this file will contain the keys from the actual .env file but with fake values.

Your collaborator can then;

  1. Create their .env file,

  2. Copy the contents of the env.example file into their .env file,

  3. Generate a secret key,

  4. Replace the sample (fake) key in the .env file with the newly generated key.

Ensure you don't forget to add .env file to .gitignore so it doesn't get pushed to your GitHub repository, thereby exposing your keys. It's better to have a sample file like env.example which can be pushed to keep track of what keys a collaborator needs to create when running the project on their machine.

Using Python Built-in Secrets Library

From Python Documentation: The secrets module is used for generating cryptographically strong random numbers suitable for managing data such as passwords, account authentication, security tokens, and related secrets.

Use the Secrets library for security purposes to generate something random, like random tokens, digits, or strings. Its randomness is cryptographically secure.

Creating a secure hex token

  • Run your Python shell.
>>> import secrets
>>> secrets.token_hex()
'20a3f7333abd0668e474d393870a0b47463a6935e2eb730343820767eaf77226'

That's a simple way to create a very secure token. The longer the token the more sufficient the randomness.

The function token_hex accepts a parameter, n_bytes, for how long you want the token.

>>> import secrets
>>> secrets.token_hex(64
'5222cffc8c2881afcbf219c90c6e2f3a8b168c7547f790c2e852a047e9f4c8094577d8198a1d802ee053d13987e9111b317a7771c9ce87597a67203311afc69f')

Read more in the Python Documentation

Now you can use generate highly secure tokens for your projects. These tokens can be used as a secret key in any project, Django, NodeJS, Golang, etc.

Conclusion

Securing web applications and software requires effective management of secret keys. Python offers libraries like cryptography and secrets that simplify the process of generating cryptographically secure tokens. To ensure maximum protection of sensitive data, it is crucial to store these keys securely using tools like Pypi Decouple and AWS Secrets Manager. By adhering to best practices for managing secret keys, developers can guarantee the security of their projects and prevent unauthorized access to sensitive information.

Read more

  1. Cryptography Algorithms - Primitives

  2. Password Vaults

  3. AWS Secrets Manager

Follow me on Twitter @netrobeweb, Hashnode, and Dev.to where I post amazing projects and articles.

Thanks for reading, 🤓😊

11
Subscribe to my newsletter

Read articles from Ayomide Ayanwola directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ayomide Ayanwola
Ayomide Ayanwola

Full stack developer | DevOps engineer | Cloud Technologist I develop software architectures for PaaS and SaaS startups and projects, deploy them on the cloud using serverless technology or Bare metal servers. I specialize in building software designs with Python, Golang and JavaScript.