Field-level encryption for Django using AES-256-GCM
Project description
django-field-encryption
Field-level and file encryption for Django using AES-256-GCM with automatic key rotation support.
Features
- Field-level encryption: Encrypt sensitive data in Django model fields
- File encryption: Encrypt uploaded files with dedicated storage backend
- Automatic key rotation: Seamlessly rotate encryption keys without data migration
- Key derivation: Separate keys for fields and files using HKDF
- Tamper detection: AES-GCM provides built-in authentication
- Multiple key support: Manage multiple encryption key versions
Installation
pip install django-field-encryption
Quick Start
- Add to your Django settings:
DATA_PROTECTION_KEYS = {
'v1': 'your-base64-encoded-32-byte-key',
}
DATA_PROTECTION_ACTIVE_KEY_ID = 'v1'
- Use the encrypted fields:
from django_field_encryption import EncryptedCharField, EncryptedTextField
class MyModel(models.Model):
secret_name = EncryptedCharField(max_length=100)
secret_notes = EncryptedTextField()
Configuration
Generate a Master Key
from django_field_encryption import generate_master_key
key = generate_master_key() # Returns base64-encoded 32-byte key
Multiple Keys and Key Rotation
DATA_PROTECTION_KEYS = {
'v1': 'old-key-base64...',
'v2': 'new-key-base64...',
}
DATA_PROTECTION_ACTIVE_KEY_ID = 'v2'
When rotating to a new key, existing encrypted data can be re-encrypted:
from django_field_encryption import FieldEncryptor
# Re-encrypt with the active key
rotated_value = FieldEncryptor.rotate_value(old_encrypted_value)
Field Types
EncryptedCharField
Encrypted character field stored as TextField:
from django_field_encryption import EncryptedCharField
class UserProfile(models.Model):
ssn = EncryptedCharField(max_length=20)
credit_card = EncryptedCharField(char_max_length=16)
EncryptedTextField
Encrypted text field for longer content:
from django_field_encryption import EncryptedTextField
class Document(models.Model):
content = EncryptedTextField()
private_notes = EncryptedTextField()
EncryptedJSONField
Encrypted JSON field with automatic serialization:
from django_field_encryption import EncryptedJSONField
class Settings(models.Model):
preferences = EncryptedJSONField()
# Usage
obj = MyModel.objects.create(
preferences={'theme': 'dark', 'notifications': True}
)
# Automatically serialized, encrypted, and stored
File Encryption
EncryptedFileStorage
Use the encrypted file storage for sensitive file uploads:
from django_field_encryption import EncryptedFileStorage
from django.db import models
class Document(models.Model):
file = models.FileField(storage=EncryptedFileStorage())
Or use the pre-configured instance:
from django_field_encryption import encrypted_file_storage
class Document(models.Model):
file = models.FileField(storage=encrypted_file_storage)
API Reference
FieldEncryptor
Low-level encryption/decryption operations:
from django_field_encryption import FieldEncryptor
# Encrypt
encrypted = FieldEncryptor.encrypt('sensitive data')
# Returns: 'v1:base64encoded...'
# Decrypt
decrypted = FieldEncryptor.decrypt(encrypted)
# Returns: 'sensitive data'
# Check if value is encrypted with a known key
can_decrypt = FieldEncryptor.can_decrypt(encrypted) # True/False
# Rotate to active key
rotated = FieldEncryptor.rotate_value(encrypted)
# Returns re-encrypted value or None if already using active key
# Clear key cache (call after changing settings in tests)
FieldEncryptor.clear_cache()
FileEncryptor
File-level encryption:
from django_field_encryption import FileEncryptor
# Encrypt bytes
encrypted, key_id = FileEncryptor.encrypt(b'sensitive file content')
# Returns: (b'ENC2...', 'v1')
# Decrypt
decrypted = FileEncryptor.decrypt(encrypted)
# Returns: b'sensitive file content'
# Check if data is encrypted
is_enc = FileEncryptor.is_encrypted(encrypted) # True/False
compute_hash
Compute a deterministic hash for indexing (without encryption):
from django_field_encryption import compute_hash
hash_value = compute_hash('29901012345678')
# Returns: 64-character hex string
BlindIndexField
Enable unique lookups on encrypted fields without decrypting:
from django_field_encryption import EncryptedCharField, BlindIndexField
class UserProfile(models.Model):
email = EncryptedCharField(max_length=255)
email_hash = BlindIndexField('email', unique=True, db_index=True)
# Lookup by hash
from django_field_encryption import compute_hash
user = UserProfile.objects.get(email_hash=compute_hash('user@example.com'))
The hash is auto-computed on save via a pre_save signal. Note that bulk_create and bulk_update do not trigger signals — hashes must be computed manually for bulk operations.
generate_master_key
Generate a cryptographically secure master key:
from django_field_encryption import generate_master_key
key = generate_master_key()
# Returns: base64-encoded 32-byte key
Configuration Functions
from django_field_encryption import (
get_keys_config,
get_active_key_id,
get_master_key,
)
keys = get_keys_config() # Returns dict of key_id -> key
active_key = get_active_key_id() # Returns currently active key_id
master_key = get_master_key('v1') # Returns raw 32-byte key for key_id
Compatibility
| Python | Django |
|---|---|
| 3.9 | 4.2, 5.x |
| 3.10 | 4.2, 5.x |
| 3.11 | 4.2, 5.x |
| 3.12 | 4.2, 5.x |
- Django 4.2 LTS is fully supported
- Django 5.0+ supported
- Will support Django 6.x when released (constraint is
<7.0)
Security Notes
- Keys are 32 bytes (256 bits) for AES-256
- Uses AES-GCM (Galois/Counter Mode) for authenticated encryption
- Each encryption generates a unique 12-byte random nonce
- Field and file keys are derived separately using HKDF
- The library does not encrypt at rest - data is encrypted/decrypted in memory only
- High-volume deployments: Rotate keys before reaching ~2³² encryptions per key to avoid nonce collision risk. See docs/security.md for details.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_field_encryption-0.1.4.tar.gz.
File metadata
- Download URL: django_field_encryption-0.1.4.tar.gz
- Upload date:
- Size: 13.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
02df2773bc0a93ccbc97b226736c7d06e34d44cf3706ea2547012c889cf9c214
|
|
| MD5 |
a1f5ee2d096b4d547ab8fb3a3119f7fc
|
|
| BLAKE2b-256 |
8c6bf4d7601942c8dd1e4f04fdfe33c838421af83ffe6986778c36d1df85c8ae
|
File details
Details for the file django_field_encryption-0.1.4-py3-none-any.whl.
File metadata
- Download URL: django_field_encryption-0.1.4-py3-none-any.whl
- Upload date:
- Size: 13.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8f0654c6d908756b8eb57b17a155dd68539ee0b09065a80f38cff7407b1a95fd
|
|
| MD5 |
c8e0d437793e71035a221e46b5c2301b
|
|
| BLAKE2b-256 |
ebb6d11c09ece9793e78b29e3eb14be65495b1525ae8adee8ba83c46cea2ce18
|