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-fieldsVerified import paths — ran on the pinned version, not inferred.
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`.
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.
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.
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.
For sensitive fields, consider making them non-nullable and storing a 'sentinel' empty value (which will be encrypted) instead of `None`.
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.
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).
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.
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`.
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.