{ "info": { "author": "Guy Willett", "author_email": "", "bugtrack_url": null, "classifiers": [ "Framework :: Django", "Framework :: Django :: 2.1", "Framework :: Django :: 2.2", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7" ], "description": "# Django Searchable Encrypted Fields\nThis package is for you if you would like to encrypt model field data \"in app\" - ie before it is sent to the database.\n\n**Why another encrypted field package?**\n\n1. We use AES-256 encryption with GCM mode (via the Pycryptodome library).\n2. There is a django command to easily generate appropriate encryption keys.\n3. You can make 'exact' search lookups when also using the SearchField.\n\n## Install & Setup\n```shell\n$ pip install django-searchable-encrypted-fields\n```\n```python\n# in settings.py\nINSTALLED_APPS += [\"encrypted_fields\"]\n\n# A list of hex-encoded 32 byte keys\n# You only need one unless/until rotating keys\nFIELD_ENCRYPTION_KEYS = [\n \"f164ec6bd6fbc4aef5647abc15199da0f9badcc1d2127bde2087ae0d794a9a0b\"\n]\n```\n\n## Intro\nThis package provides two types of model field for Django.\n1. A series of **EncryptedField** classes which can be used by themselves and work just like their regular Django counterparts. Contents are transparently encrypted/decrypted.\n2. 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.\n\nThis is probably best demonstrated by example:\n\n## Using a stand-alone EncryptedField\n```python\nfrom encrypted_fields import fields\n\nclass Person(models.Model):\n favorite_number = fields.EncryptedIntegerField(help_text=\"Your favorite number.\")\n```\nYou can use all the usual field arguments and add validators as normal.\nNote, however, that primary_key, unique and db_index are not supported because they do not make sense for encrypted data.\n\n\n## Using a SearchField along with an EncryptedField\n```python\nclass Person(models.Model):\n _name_data = fields.EncryptedCharField(max_length=50, editable=False)\n name = fields.SearchField(encrypted_data_field=\"_name_data\", hash_key=\"f164ec6bd...7ae0d794a9a0b\")\n favorite_number = fields.EncryptedIntegerField()\n city = models.CharField(max_length=255) # regular Django model field\n```\nYou can then use it like:\n```python\n# \"Jo\" is hashed and stored in 'name' as well as symmetrically encrypted and stored in '_name_data'\nPerson.objects.create(name=\"Jo\", favorite_number=7, city=\"London\")\nperson = Person.objects.get(name=\"Jo\")\nassert person.name == \"Jo\"\nassert person.favorite_number == 7\n\nperson = Person.objects.get(city=\"London\")\nassert person.name == \"Jo\" . # the data is taken from '_name_data', which decrypts it first.\n```\nYou can safely update like this:\n```python\nperson.name = \"Simon\"\nperson.save()\n```\nBut when using `update()` you need to provide the value to both fields:\n```python\nPerson.objects.filter(name=\"Jo\").update(name=\"Bob\", _name_data=\"Bob\")\n```\nA SearchField inherits the validators and formfield (widget) from its associated EncryptedField. So:\n\n1. Do not add validators or form widgets to SearchFields (they will be ignored), add them to the associated EncryptedField instead.\n2. Do not include the EncryptedField in forms, instead just display the SearchField.\n\n## Included EncryptedField classes\nThe following are included:\n```python\n\"EncryptedFieldMixin\",\n\"EncryptedTextField\",\n\"EncryptedCharField\",\n\"EncryptedEmailField\",\n\"EncryptedIntegerField\",\n\"EncryptedDateField\",\n\"EncryptedDateTimeField\",\n\"EncryptedBigIntegerField\",\n\"EncryptedPositiveIntegerField\",\n\"EncryptedPositiveSmallIntegerField\",\n\"EncryptedSmallIntegerField\",\n```\nNote that, although untested, you should be able to extend other regular Django model field classes like this:\n```python\nclass EncryptedIPAddressField(EncryptedFieldMixin, models.GenericIPAddressField):\n pass\n```\nPlease let us know if you have problems when doing this.\n## Generating Encryption Keys\nYou can use the included Django management command which 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:\n```shell\n$ python manage.py generate_key\n```\nNote: encryption keys **must** be hex encoded and 32 bytes\n\n**Important**: use different hash_key values for each SearchField and make sure they are different from any keys in `settings.FIELD_ENCRYPTION_KEYS`.\n## Rotating Encryption Keys\nIf 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.\n## Compatability\n`django-searchable-encrypted-fields` is tested with Django(2.1, 2.2) on Python(3.6, 3.7) using SQLite and PostgreSQL.\n\nTest coverage is at 96%.", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://gitlab.com/guywillett/django-searchable-encrypted-fields", "keywords": "", "license": "MIT", "maintainer": "Guy Willett", "maintainer_email": "", "name": "django-searchable-encrypted-fields", "package_url": "https://pypi.org/project/django-searchable-encrypted-fields/", "platform": "", "project_url": "https://pypi.org/project/django-searchable-encrypted-fields/", "project_urls": { "Homepage": "https://gitlab.com/guywillett/django-searchable-encrypted-fields" }, "release_url": "https://pypi.org/project/django-searchable-encrypted-fields/0.1.3/", "requires_dist": null, "requires_python": "", "summary": "Django model fields encrypted using Pycryptodome AES-256 GCM.", "version": "0.1.3" }, "last_serial": 5129851, "releases": { "0.1.3": [ { "comment_text": "", "digests": { "md5": "372d06de6fc471d4328d7979d315b5ad", "sha256": "7e5008d3d496193e48d9e0bb099d7411733d8db2ee8e81a54a99cfac613d3da1" }, "downloads": -1, "filename": "django-searchable-encrypted-fields-0.1.3.tar.gz", "has_sig": false, "md5_digest": "372d06de6fc471d4328d7979d315b5ad", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6551, "upload_time": "2019-04-11T16:33:20", "url": "https://files.pythonhosted.org/packages/d9/42/436a1f9287b9a6c39f6cc8afb671b2b6c2ed07ed8b1418bf1e3c39856085/django-searchable-encrypted-fields-0.1.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "372d06de6fc471d4328d7979d315b5ad", "sha256": "7e5008d3d496193e48d9e0bb099d7411733d8db2ee8e81a54a99cfac613d3da1" }, "downloads": -1, "filename": "django-searchable-encrypted-fields-0.1.3.tar.gz", "has_sig": false, "md5_digest": "372d06de6fc471d4328d7979d315b5ad", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6551, "upload_time": "2019-04-11T16:33:20", "url": "https://files.pythonhosted.org/packages/d9/42/436a1f9287b9a6c39f6cc8afb671b2b6c2ed07ed8b1418bf1e3c39856085/django-searchable-encrypted-fields-0.1.3.tar.gz" } ] }