Registry / auth-security / django-fernet-encrypted-fields

django-fernet-encrypted-fields

JSON →
library0.4.0pypypi✓ verified 86d ago

django-fernet-encrypted-fields provides symmetrically encrypted model fields for Django, leveraging Fernet encryption from the `cryptography` library. It ensures that data is encrypted before being stored in the database and automatically decrypted when accessed in the application. This library is actively maintained as part of the Jazzband project, with recent updates and a focus on security for sensitive data at rest.

pip install django-fernet-encrypted-fields
INSTALL
IMPORT
SIG · DJANGO-FERNET-ENCR
D
django-fernet-encrypted-fields
auth-securitypythonv0.4.0
Install
4.2s avg
Import
641ms
Disk
82MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v0.4.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.920 runs
installs and imports cleanly · install 0.0s · import 0.664s · 82.6MB
glibc
py 3.103.920 runs
installs and imports cleanly · install 4.2s · import 0.619s · 83MB
82MB installed
● package 82MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

EncryptedCharField
from encrypted_fields.fields import EncryptedCharField
EncryptedTextField
from encrypted_fields.fields import EncryptedTextField
EncryptedIntegerField
from encrypted_fields.fields import EncryptedIntegerField
EncryptedEmailField
from encrypted_fields.fields import EncryptedEmailField
* (wildcard import)
from encrypted_fields.fields import EncryptedTextField
from encrypted_fields.fields import *
While functional, wildcard imports are generally discouraged for clarity and to prevent namespace pollution.
EncryptedTextField (from old package)
from encrypted_fields.fields import EncryptedTextField
from fernet_fields import EncryptedTextField
This import path belongs to an older, different package (`django-fernet-fields`) and will not work with `django-fernet-encrypted-fields`.

To get started, install the library and configure your `settings.py` with a `SALT_KEY` (or rely on `SECRET_KEY` as a fallback, which is less secure for specific field encryption). Define your model with an `EncryptedTextField` or other provided encrypted field types. Data will be automatically encrypted and decrypted during save and retrieve operations. Remember to run `makemigrations` and `migrate`.

import os from django.db import models from encrypted_fields.fields import EncryptedTextField # In your Django settings.py file, define SALT_KEY # For production, load from environment variables and ensure it's a strong, random string. # Example for settings.py (not for production directly): # import os # os.environ.setdefault('DJANGO_SALT_KEY', '0123456789abcdefghijklmnopqrstuvwxyz') SALT_KEY = os.environ.get('DJANGO_SALT_KEY', 'a_default_32_char_salt_key_for_dev') # For Django >= 4.1, you can also use SECRET_KEY_FALLBACKS for SECRET_KEY rotation. # SECRET_KEY_FALLBACKS = [os.environ.get('OLD_DJANGO_SECRET_KEY', '')] class MyEncryptedModel(models.Model): sensitive_data = EncryptedTextField() name = models.CharField(max_length=255) def __str__(self): return self.name # Example usage (assuming Django setup and migrations are run): # from myapp.models import MyEncryptedModel # instance = MyEncryptedModel.objects.create(name='Test User', sensitive_data='This is a secret message.') # print(instance.sensitive_data) # Automatically decrypted: 'This is a secret message.' # print(instance.pk)
Debug
Known issues
breakingChanging an existing unencrypted field to an encrypted field, or vice-versa, requires a complex three-step data migration: add a new field (nullable), copy data using a data migration (which encrypts/decrypts), then remove the old field and optionally rename the new one. Direct field type changes in `models.py` will result in data loss or unreadable data.
fix
Follow the three-step data migration process: 1. Add new encrypted field with a different name and `null=True`. 2. Create a data migration to copy values from old to new field. 3. Remove the old field and rename the new field if desired.
affects: All versions
gotchaFernet encryption is non-deterministic, meaning the same plaintext encrypts to a different ciphertext each time. This makes encrypted fields unsuitable for database indexing (`db_index=True`, `unique=True`, `primary_key=True`), lookups (other than `isnull`), or meaningful ordering, as these operations would be performed on the unhelpful ciphertext. Setting `db_index=True`, `unique=True`, or `primary_key=True` will raise a `django.core.exceptions.ImproperlyConfigured` error.
fix
Avoid using `db_index=True`, `unique=True`, or `primary_key=True` on `EncryptedField` instances. Design your schema such that lookups and indexing are performed on unencrypted, non-sensitive fields.
affects: All versions
breakingLoss of the `SALT_KEY` (or `SECRET_KEY` if `SALT_KEY` is not set) will render all encrypted data irrecoverable. The security of your encrypted data is entirely dependent on the secrecy and retention of this key.
fix
Store `SALT_KEY` in a secure environment variable or secrets management system. Implement robust backup procedures for your keys. For key rotation, use `SALT_KEY` as a list of keys, or `SECRET_KEY_FALLBACKS` (Django >= 4.1) for `SECRET_KEY` rotation.
affects: All versions
gotchaNullable encrypted fields (`null=True`) trivially reveal the presence or absence of data to an attacker. If this is a concern, avoid nullable encrypted fields.
fix
For sensitive fields, consider making them non-nullable and storing a 'sentinel' empty value (which will be encrypted) instead of `None`.
affects: All versions
gotchaWhen deploying to platforms like Heroku, explicit pinning of `cryptography` and its underlying C library `libffi` might be required in `requirements.txt` to ensure proper build and deployment.
fix
Ensure `cryptography` is explicitly listed in `requirements.txt` with a version pin. Run `pip freeze > requirements.txt` after installing all dependencies in a clean virtual environment.
affects: All versions
Errors
Common errors & fixes
InvalidToken / Cannot decrypt data
The encryption key (`SALT_KEY` or `SECRET_KEY`) used to decrypt the data is different from the key used to encrypt it, or the data has been corrupted.
fix
Verify that your `SALT_KEY` (or `SECRET_KEY`) in `settings.py` or environment variables matches the key used when the data was originally saved. Ensure no data corruption occurred. For key rotation, ensure all valid keys are provided in the `SALT_KEY` list or `SECRET_KEY_FALLBACKS` (Django >= 4.1).
django.core.exceptions.ImproperlyConfigured: EncryptedField cannot be indexed.
An `EncryptedField` (or its subclasses) has `db_index=True`, `unique=True`, or `primary_key=True` set.
fix
Remove `db_index=True`, `unique=True`, and `primary_key=True` from the `EncryptedField` definition in your model. Encrypted data is not suitable for these database constraints.
incorrect padding
The Fernet key provided (either `SALT_KEY` or `SECRET_KEY` if `SALT_KEY` is not used) is not a valid 32-bit URL-safe base64-encoded bytestring, or the data is corrupted. This can happen if `FERNET_USE_HKDF = False` (from related libraries) and the key is not correctly formatted.
fix
Ensure your `SALT_KEY` (or `SECRET_KEY`) is a correctly generated Fernet-compatible key. When `SALT_KEY` is used, the library handles the HKDF derivation, so ensure `SALT_KEY` is a strong, random string. If manually managing Fernet keys (not common with this library), generate them using `Fernet.generate_key()` from `cryptography`.
Data too long for field (e.g., 'value too long for type character varying(X)')
Encrypted data is typically longer than the original plaintext. The `max_length` of the underlying `CharField` might be insufficient.
fix
Increase the `max_length` attribute for `EncryptedCharField` instances to accommodate the increased size of encrypted data. `EncryptedTextField` does not have a `max_length` limit, making it suitable for longer encrypted strings.
Upgrade
Version history
0.4.0latest on PyPI · released Apr 14, 2026
Audit
Dependencies
DjangorequiredCore framework dependency for model fields.
cryptographyrequiredProvides the underlying Fernet symmetric encryption primitive.
Agent activity
20 hits · last 30 days
node
18
OpenAI (training)
1
Resources
django-fernet-encrypted-fields — pip install django-fernet-encrypted-fields · libregistry