Package: django-encrypted-json-fields
Django Encrypted Model Fields (including JSONField)AboutThis is a fork ofhttps://gitlab.com/lansharkconsulting/django/django-encrypted-model-fields,
which in turn was a fork ofhttps://github.com/foundertherapy/django-cryptographic-fields.It has been renamed, and updated to properly support Python3 and the latest
versions of Django.django-encrypted-json-fieldsis set of fields that wrap standard
Django fields with encryption provided by the python cryptography
library. These fields are much more compatible with a 12-factor design
since they take their encryption key from the settings file instead of a
file on disk used bykeyczar.While keyczar is an excellent tool to use for encryption, it's not
compatible with Python 3, and it requires, for hosts like Heroku, that
you either check your key file into your git repository for deployment,
or implement manual post-deployment processing to write the key stored
in an environment variable into a file that keyczar can read.JSONField supportdjango-encrypted-json-fieldsextends the origin projectdjango-encrypted-model-fieldsby adding a specific support for JSONFields, with the following features:the encrypted data remains a valid JSON, so you can inherit from django.db.models.JSONField and all validations will still workif the data contains dictionaries, the keys are preserved so that the overall structure remains intactthat is: we only encrypt the valuesImplementation notesI opted to encrypt the repr() of the values, then apply eval() later only (after decrypting).This is usefull to reconstructboth the value and the type; since JSON manages
only a few simple types, this naive solution just fits the bill.The crypterAll functions responsible for encryption/decryption (see below) require acrypter, which
can be obtained in a few ways:default crypter: assign a key or a list of keys to theEJF_ENCRYPTION_KEYSsetting,
and a default crypter will be build for youassigning a callable to theEJF_ENCRYPTION_KEYSsetting, which in turn will
return a list of keys as aboveinvokebuild_crypter(keys)explicitly, and pass the resulting object aroundFor the latter, the use case I had in mind was the need to keep the data in play text
on the server, and export encrypted data for a remote client, sharing a common key.Deferred get_crypter()SinceEJF_ENCRYPTION_KEYSsetting now accepts a callable, which might very well
need to retrieve some data from the Django models, I had to postpone the call to
get_crypter() until all apps have been loaded.As a side effect, now you can always and safely call thegenerate_encryption_keymanagement command (see below)App settingsEJF_ENCRYPTION_KEYSeither a key, a list of keys, or a callable returning the list of keys to
be used for building the default crypterEJF_DISABLE_ENCRYPTIONskip encryption when saving the model (save data unencrypted)HelpersAll function used internally when saving and reading Django models can also be
invoked explicitly to apply encryption/decryption to arbitrary strings or JSON
values.A possible use case consists in serializing encrypted data to be sent to a remote
client.FunctionPurponegenerate_random_encryption_key()generate a keybuild_crypter(keys)given a list of keys (or a key) builds the corresponding crypteris_encrypted(s: Union[str, bytes]) -> boolCheck if the given string (or bytes) is the result of an encryptionencrypt_str(s: str, crypter=None, force=False) -> bytesEncrypts the given string applying either the supplied crypter or, in None, the default crypterdecrypt_bytes(t: bytes, crypter=None, force=False) -> strDecrypts the given bytes and returns a stringencrypt_values(data, crypter=None, force=False, json_skip_keys=None)Applyes encryption to a JSON-serializable objectdecrypt_values(data, crypter=None, force=False)reverses encrypt_values()force means: proceed even when encryption is disabled in project's settingsManagment commandsSome management commands are supplied; run with--helpfor detailed informations:generate_encryption_keyencrypt_strdecrypt_strencrypt_all_tablesdecrypt_all_tablesGetting Started$ pip install django-encrypted-json-fieldsAdd "encrypted_json_fields" to your INSTALLED_APPS setting like this:INSTALLED_APPS = (
        ...
        'encrypted_json_fields',
    )django-encrypted-json-fieldsexpects the encryption key to be
specified usingFIELD_ENCRYPTION_KEYin your project'ssettings.pyfile. For example, to load it from the local environment:import os

    FIELD_ENCRYPTION_KEY = os.environ.get('FIELD_ENCRYPTION_KEY', '')To use an encrypted field in a Django model, use one of the fields from
theencrypted_json_fieldsmodule:from encrypted_json_fields.fields import EncryptedCharField

    class EncryptedFieldModel(models.Model):
        encrypted_char_field = EncryptedCharField(max_length=100)For fields that requiremax_lengthto be specified, theEncryptedvariants of those fields will automatically increase the size of the
database field to hold the encrypted form of the content. For example, a
3 character CharField will automatically specify a database field size
of 100 characters whenEncryptedCharField(max_length=3)is specified.Due to the nature of the encrypted data, filtering by values contained
in encrypted fields won't work properly. Sorting is also not supported.Running TestsDoes the code actually work?Running the unit tests from this app:python manage.py test -v 2or./runtests.pyorcoverage run --source='.' runtests.py
coverage reportSample projectA sample project using this app for demonstration purposes is available here:https://github.com/morlandi/test_django_encrypted_json_fieldsCreditshttps://gitlab.com/lansharkconsulting/django/django-encrypted-model-fieldshas been shared by Scott Sharkeyhttps://github.com/foundertherapy/django-cryptographic-fieldshas been shared by Dana Spiegeldjango-encrypted-model-fields Changelog1.0.4 - fix fetch_raw_field_value() for sqlite1.0.3 - prevent double encryption1.0.2 - "force" flag added1.0.0 - helpers available as standalone funcsmajor refactoringmore unit tests0.7.2 - More hacks to optionally disable encryption of JSON fields0.7.1 - Overridable crypterOptionally disable encryption withFIELD_SKIP_ENCRYPTION0.7.0 - JSONField supportdeferred get_crypter()FIELD_ENCRYPTION_KEYsetting now accepts a callable0.6.5 - RE-Correct links to repository and homepage0.6.4 - Correct links to repository and homepage0.6.3 - Converted to poetry for build system0.6.2 - Bump support to any python < 4Make Generating an Encryption Key more prominent0.6.1 - Add Support for Python up to 3.110.6.0 - Major UpdateDrop Python 2 SupportDrop support for Django < 2.2Add support for Django 2.2, 3.0, 3.1, and 3.2Drop support for Python < 3.6Add Support for Python 3.6, 3.7, 3.8, and 3.9Move travis-ci testing to gitlabRemove Support for EncryptedNullBooleanField (deprecated by
Django 4.0)Update Test App to Django 2.2 standardInclude 2 of Oleg Pesok's fixes: for Timezone-aware datetimes,
and the cached validator crash0.5.8 - Move to GITLAB repository0.5.7 - rearrange requirements and update dependenciesfix issue with output of generate_encryption_key commanddefine default value for FIELD_ENCRYPTION_KEYrestore support for Django 1.9, 1.10, and 1.110.5.6 - Fixed issue with generating encryption keys (thanks Dave
Alan)dropped support for Django 1.8, 1.9 and 1.10fix classifier to include Django 2.00.5.5 - Fixed README0.5.4 - drop python 3.4 supportadd django 2.0 supportexpand testing to cover python 2.7, 3.5 and 3.6 for django 1.9,
1.10, 1.11 and 2.0fix broken test0.5.3 - Fork from foundertherapy/django-cryptographic-fieldsupdate dependenciesconvert to run under python 3.xrename package so it can be uploaded to pypiadd support for tox/travis-ci testing