Built-in encrypted fields
- Dominant language
- No language data
- Stars
- 188
- Forks
- 7
- PR merge metrics
- No merged PRs in 30d
Description
### Code of Conduct
- [x] I agree to follow Django's Code of Conduct
### Feature Description
This is a proposal for the implementation of a built-in encrypted field in Django. The goal is to store data encrypted at rest at the database, while also maintaining data type validation at the front-end.
Two functionalities that we believe are important in this scope are:
- Data type agnostic field (e.g. not implement `EncryptedCharField`, `EncryptedPositiveIntegerField` etc.), but use a single `EncryptedField` that could also support custom fields out of the box, for data validation and whidget rendering
- Support reading and displaying the decrypted contents to the end user to support use cases like messaging applications, where the encyrpted data also has to be read.
### Problem
There is no built-in functionality to store sensitive data encrypted in the database, that also have to be able to be retrieved and decrypted. This is relevant for a few different use cases, from storing credentials (e.g. API keys) to sensitive personal data.
The threat model we are trying to mitigate is exposure of sensitive data to potential attackers that compromise the database server.
### Request or proposal
request
### Additional Details
There are a few key decisions that have to be made in order to implement this feature. The most important of which is the **encryption mechanism**. Here we essentially have two options.
**Encrypt at the database** (e.g. with `pgcrypto`). This can enable faster operations and even some filtering and querying, but at the expense of:
- Security (e.g. encryption keys can leak at database logs)
- Cross database backend support, as not all database engines support natively encryption function (e.g. sqlite3 does not)
**Encrypt with Python** (e.g. Fernet with `cryptography` package). This provides a more secure option, but at the expense of:
- Performance, as Python encryption / descryption operations are usually slower
- Functionality, as there is virtually no filtering / querying capabilities
- Additional package needed, from what I can tell, which introduces a new dependency and could widen supply chain attack scenarios.
Feedback here would be much appreciated.
#### Existing implementations
- https://github.com/jazzband/django-fernet-encrypted-fields
- https://github.com/getsentry/sentry/pull/95542
- https://github.com/incuna/django-pgcrypto-fields
- https://gitlab.com/lansharkconsulting/django/django-encrypted-model-fields
### Implementation Suggestions
In an internal Django project, we tried to stay as close as possible to how `ArrayField` implemented `base_field` to minimise mental load. The encryption key we used was `SECRET_KEY` from settings, although key rotation should also be supported at least to some extent.
Below is an example high-level model that that could hold sensitive data of various types for a person:
```py
class Person(models.Model):
credentials = EncryptedField(
base_field=models.JSONField(),
default=dict,
blank=True,
verbose_name=_("Credentials in JSON format"),
)
addresses = EncryptedField(
base_field=ArrayField(
base_field=models.CharField(max_length=32),
),
verbose_name=_("Addresses of people"),
blank=True,
default=list,
)
date_of_birth = EncryptedField(
base_field=models.DateTimeField(),
blank=True,
null=True,
verbose_name=_("Date of birth"),
)
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.