Django model fields encrypted using Pycryptodome AES-256 GCM.
Project description
Django Searchable Encrypted Fields
This package is for you if you would like to encrypt model field data "in app" - ie before it is sent to the database.
Why another encrypted field package?
- We use AES-256 encryption with GCM mode (via the Pycryptodome library).
- It is easy to generate appropriate encryption keys with
secrets.token_hex(32)
from the standard library. - You can make 'exact' search lookups when also using the SearchField.
Install & Setup
$ pip install django-searchable-encrypted-fields
# in settings.py
INSTALLED_APPS += ["encrypted_fields"]
# A list of hex-encoded 32 byte keys
# You only need one unless/until rotating keys
FIELD_ENCRYPTION_KEYS = [
"f164ec6bd6fbc4aef5647abc15199da0f9badcc1d2127bde2087ae0d794a9a0b"
]
Intro
This package provides two types of model field for Django.
- A series of EncryptedField classes which can be used by themselves and work just like their regular Django counterparts. Contents are transparently encrypted/decrypted.
- A SearchField which can be used in conjunction with any EncryptedField. Values are concatentaed with a
hash_key
and then hashed with SHA256 before storing in a separate field. This means 'exact' searches can be performed.
This is probably best demonstrated by example:
Using a stand-alone EncryptedField
from encrypted_fields import fields
class Person(models.Model):
favorite_number = fields.EncryptedIntegerField(help_text="Your favorite number.")
You can use all the usual field arguments and add validators as normal. Note, however, that primary_key, unique and db_index are not supported because they do not make sense for encrypted data.
Using a SearchField along with an EncryptedField
class Person(models.Model):
_name_data = fields.EncryptedCharField(max_length=50, editable=False)
name = fields.SearchField(hash_key="f164ec6bd...7ae0d794a9a0b", encrypted_field_name="_name_data", )
favorite_number = fields.EncryptedIntegerField()
city = models.CharField(max_length=255) # regular Django model field
You can then use it like:
# "Jo" is hashed and stored in 'name' as well as symmetrically encrypted and stored in '_name_data'
Person.objects.create(name="Jo", favorite_number=7, city="London")
person = Person.objects.get(name="Jo")
assert person.name == "Jo"
assert person.favorite_number == 7
person = Person.objects.get(city="London")
assert person.name == "Jo" . # the data is taken from '_name_data', which decrypts it first.
You can safely update like this:
person.name = "Simon"
person.save()
But when using update()
you need to provide the value to both fields:
Person.objects.filter(name="Jo").update(name="Bob", _name_data="Bob")
A SearchField inherits the validators and formfield (widget) from its associated EncryptedField. So:
- Do not add validators or form widgets to SearchFields (they will be ignored), add them to the associated EncryptedField instead.
- Do not include the EncryptedField in forms, instead just display the SearchField.
Included EncryptedField classes
The following are included:
"EncryptedFieldMixin",
"EncryptedTextField",
"EncryptedCharField",
"EncryptedEmailField",
"EncryptedIntegerField",
"EncryptedDateField",
"EncryptedDateTimeField",
"EncryptedBigIntegerField",
"EncryptedPositiveIntegerField",
"EncryptedPositiveSmallIntegerField",
"EncryptedSmallIntegerField",
Note that, although untested, you should be able to extend other regular Django model field classes like this:
class EncryptedIPAddressField(EncryptedFieldMixin, models.GenericIPAddressField):
pass
Please let us know if you have problems when doing this.
Generating Encryption Keys
You can use secrets
from the standard library. It will print appropriate hex-encoded keys to the terminal, ready to be used in settings.FIELD_ENCRYPTION_KEYS
or as a hash_key for a SearchField:
$ python manage.py shell
>>> import secrets
>>> secrets.token_hex(32)
Note: Thanks to Andrew Mendoza for the suggestion.
Note: encryption keys must be hex encoded and 32 bytes
Important: use different hash_key values for each SearchField and make sure they are different from any keys in settings.FIELD_ENCRYPTION_KEYS
.
Rotating Encryption Keys
If you want to rotate the encryption key just prepend settings.FIELD_ENCRYPTION_KEYS
with a new key. This new key (the first in the list) will be used for encrypting/decrypting all data. If decrypting data fails (because it was encrypted with an older key), each key in the list is tried.
Compatability
django-searchable-encrypted-fields
is tested with Django(2.1, 2.2) on Python(3.6, 3.7) using SQLite and PostgreSQL.
Test coverage is at 96%.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Hashes for django-searchable-encrypted-fields-0.1.4.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | 47e2f25e4b64a6139893e9d4517cae53700ad1d15fe6d6194940cc20fa0a6f75 |
|
MD5 | 5e77e4349306bc5dcdefc25e0fe60bbf |
|
BLAKE2b-256 | 1568b87f05eb579f5fdceefc3a3b01c5ea8e48a98b589834db01bb4f13af5c99 |