Django Cryptography
django-cryptography simplifies encrypting data within Django models and applications. It provides encrypted model fields and utilities based on the `cryptography` library. The current version is 1.1, with releases occurring periodically to maintain compatibility with Django and the underlying `cryptography` library.
Common errors
-
django.core.exceptions.ImproperlyConfigured: The DJANGO_CRYPTOGRAPHY_KEY setting must be configured.
cause The `DJANGO_CRYPTOGRAPHY_KEY` setting is not found or is an empty string in your Django `settings.py`.fixSet `DJANGO_CRYPTOGRAPHY_KEY = os.environ.get('DJANGO_CRYPTOGRAPHY_KEY')` in your `settings.py` and ensure the `DJANGO_CRYPTOGRAPHY_KEY` environment variable is set with a valid base64-encoded Fernet key. Example: `export DJANGO_CRYPTOGRAPHY_KEY="$(python -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())')"`. -
cryptography.fernet.InvalidToken: Token is not URL-safe base64-encoded
cause The `DJANGO_CRYPTOGRAPHY_KEY` is not a correctly formatted base64-encoded Fernet key, or the encrypted data itself is corrupted/invalid.fixVerify that your `DJANGO_CRYPTOGRAPHY_KEY` is exactly as generated by `Fernet.generate_key().decode()`. If the key is correct, the data itself might be corrupted or encrypted with a different key. Ensure the same key is used for encryption and decryption. -
ModuleNotFoundError: No module named 'django_cryptography'
cause The `django-cryptography` package is not installed or not added to your `INSTALLED_APPS`.fixFirst, ensure it's installed: `pip install django-cryptography`. Second, add `'django_cryptography'` to your `INSTALLED_APPS` list in `settings.py`. -
AttributeError: 'module' object has no attribute 'KeyGeneratingEncryptedField'
cause You are trying to import `KeyGeneratingEncryptedField`, which was removed in version 1.0 of `django-cryptography`.fixRemove any references to `KeyGeneratingEncryptedField` from your models and code. Manage your encryption key explicitly via the `DJANGO_CRYPTOGRAPHY_KEY` setting.
Warnings
- breaking Version 1.0 introduced significant breaking changes to key management. The `KEY_NAME` and `KEY_STORE` settings were removed, and the `DJANGO_CRYPTOGRAPHY_KEY` setting (loaded from an environment variable) became the sole method for providing the encryption key.
- breaking The `KeyGeneratingEncryptedField` was removed in version 1.0, simplifying the API by making key management an application-level concern via settings.
- gotcha The `DJANGO_CRYPTOGRAPHY_KEY` must be a valid base64-encoded Fernet key. If it's missing, malformed, or doesn't match the key used for encryption, data will not be encrypted/decrypted correctly, leading to `InvalidToken` errors.
- gotcha Changing an existing `CharField` or `TextField` to an `EncryptedCharField` or `EncryptedTextField` on a model with existing data requires a data migration to encrypt the old data. A simple `makemigrations` and `migrate` will not automatically encrypt existing plaintext data.
Install
-
pip install django-cryptography
Imports
- EncryptedCharField
from django_cryptography.fields import EncryptedCharField
- EncryptedTextField
from django_cryptography.fields import EncryptedTextField
- encrypt
from django_cryptography.core import encrypt
- decrypt
from django_cryptography.core import decrypt
- KeyGeneratingEncryptedField
from django_cryptography.fields import KeyGeneratingEncryptedField
N/A (removed in v1.0)
Quickstart
import os
# settings.py
INSTALLED_APPS = [
# ...
'django_cryptography',
]
# Generate a key once with: `from cryptography.fernet import Fernet; Fernet.generate_key().decode()`
# Set this as an environment variable, e.g., export DJANGO_CRYPTOGRAPHY_KEY='YOUR_GENERATED_KEY'
DJANGO_CRYPTOGRAPHY_KEY = os.environ.get('DJANGO_CRYPTOGRAPHY_KEY', '')
# myapp/models.py
from django.db import models
from django_cryptography.fields import EncryptedCharField
class SecretNote(models.Model):
title = models.CharField(max_length=100)
content = EncryptedCharField(max_length=500)
def __str__(self):
return self.title
# Example usage in a Django shell or view:
# from myapp.models import SecretNote
# note = SecretNote.objects.create(title='Top Secret', content='This is highly confidential information.')
# print(note.content) # decrypted value
# stored_value = SecretNote.objects.values_list('content', flat=True).get(pk=note.pk) # will be encrypted bytes
# print(f"Stored (encrypted): {stored_value}")