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

django-fernet-fields-v2

JSON →
library0.9pypypi✓ verified 23d ago

django-fernet-fields-v2 provides Fernet symmetric encryption for Django model fields, leveraging the `cryptography` library. It is a fork of `django-fernet-fields`, specifically updated to support Django 4 and later versions, as well as Python 3.8+. The current version is 0.9, released in August 2023, with releases typically occurring on an as-needed basis to maintain compatibility.

pip install django-fernet-fields-v2
INSTALL
IMPORT
SIG · DJANGO-FERNET-FIEL
D
django-fernet-fields-v2
auth-securitypythonv0.9
Install
4.3s avg
Import
720ms
Disk
83MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v0.9 · 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.95 runs
installs and imports cleanly · install 0.0s · import 0.748s · 83.3MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 4.3s · import 0.692s · 84MB
83MB installed
● package 83MB
Code
Verified usage

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

EncryptedField
from fernet_fields import EncryptedField
from fernet_fields import FernetCharField
EncryptedCharField
from fernet_fields import EncryptedCharField
EncryptedTextField
from fernet_fields import EncryptedTextField

To use `django-fernet-fields-v2`, define encrypted fields in your Django models by importing them from `fernet_fields`. Ensure your `settings.py` includes a `SECRET_KEY` (which it uses by default) or `FERNET_KEYS` for explicit key management. Then, create and apply migrations as usual. Data assigned to these fields will be automatically encrypted before saving to the database and decrypted upon retrieval.

import os from django.db import models from django.conf import settings from fernet_fields import FernetTextField # Minimum Django settings for model use settings.configure( SECRET_KEY=os.environ.get('DJANGO_SECRET_KEY', 'a-very-secret-key-for-testing-only-do-not-use-in-prod'), DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}}, INSTALLED_APPS=['fernet_fields'], ) # Define a model with an encrypted text field class MyEncryptedModel(models.Model): secret_data = FernetTextField() def __str__(self): return f"Encrypted ID: {self.id}" # Example usage (after migrations, typically via manage.py) # In a real application, you would run makemigrations and migrate. # For this quickstart, we'll simulate it for demonstration. if not settings.configured: settings.configure(DEBUG=True, SECRET_KEY='dummy-key', INSTALLED_APPS=['fernet_fields']) # Note: In a real Django project, you would create and apply migrations. # For a standalone runnable example, we bypass direct model setup. # from django.apps import apps; apps.populate(settings.INSTALLED_APPS) # This part requires a proper Django setup with migrations applied. # For demonstration, assume model and database are ready. # from django.db import connection # with connection.schema_editor() as schema_editor: # schema_editor.create_model(MyEncryptedModel) # Demonstrate field usage (conceptually) # If MyEncryptedModel was properly migrated: # instance = MyEncryptedModel.objects.create(secret_data='This is highly sensitive information.') # print(f"Saved encrypted data. Retrieved: {instance.secret_data}") # print(f"Data in DB (would be encrypted): {MyEncryptedModel.objects.get(id=instance.id).secret_data}") print("To run this, integrate into a Django project, define FERNET_KEYS or SECRET_KEY, and apply migrations.") print("Example model `MyEncryptedModel` defined with `secret_data = FernetTextField()`")
Debug
Known issues
breakingLoss of encryption keys will result in permanent data loss. If the `SECRET_KEY` (or any key in `FERNET_KEYS`) used to encrypt data is lost, that data becomes irrecoverable.
fix
Securely store your `SECRET_KEY` and any `FERNET_KEYS` in environment variables or a secrets management system. Implement robust backup strategies for your keys.
affects: All versions
gotchaFernet encryption is non-deterministic, meaning the same plaintext encrypts to different ciphertext each time. This makes database indexing, unique constraints, and direct lookups (e.g., `filter(field='value')`) on encrypted fields impossible or meaningless, and can raise `django.core.exceptions.ValidationError` or similar errors if attempted.
fix
Avoid applying `db_index=True` or `unique=True` to Fernet fields. For searchability or uniqueness, consider storing a hashed, non-sensitive version of the data in a separate, non-encrypted field, or design your application to retrieve and filter data in memory after decryption.
affects: All versions
gotchaWhen rotating encryption keys using `FERNET_KEYS`, new data will be encrypted with the first key in the list, but old data must be manually re-encrypted if you want it to use the new key for future saves. Simply changing `FERNET_KEYS` will not automatically re-encrypt existing data in the database.
fix
For full key rotation, you must perform a data migration. This typically involves iterating through all instances of models with encrypted fields, re-saving them (`instance.save()`) after the new key is placed at the head of `FERNET_KEYS`. Ensure old keys remain in `FERNET_KEYS` (after the new key) until all data is re-encrypted to allow decryption of existing values during the transition.
affects: All versions
gotchaEncrypted data is generally longer than its plaintext counterpart. If you use `FernetCharField`, you must ensure `max_length` is sufficient to accommodate the encrypted string, otherwise data truncation or validation errors may occur.
fix
Increase the `max_length` of `FernetCharField` fields beyond what would be needed for the plaintext. A common recommendation is to allow for at least 2x-3x the original length, plus a small overhead (e.g., if plaintext is 255 chars, use 765 or more).
affects: All versions
gotchaUsing nullable encrypted fields (`blank=True, null=True`) can inadvertently leak information about the presence or absence of data, as a `NULL` in the database trivially indicates an empty field.
fix
If this information leakage is a concern, avoid nullable encrypted fields. Instead, store a specific 'empty' sentinel value (which will be encrypted like any other data) in a non-nullable encrypted field.
affects: All versions
Upgrade
Version history
0.9latest on PyPI · released Aug 15, 2023
Audit
Dependencies
DjangorequiredRequired for Django model integration.
cryptographyrequiredProvides the underlying Fernet encryption capabilities.
Agent activity
27 hits · last 30 days
node
24
OpenAI (training)
2
Resources
django-fernet-fields-v2 — pip install django-fernet-fields-v2 · libregistry