Making your Django site GDPR-compliant

May 1, 2018

As Gary Hibberd said in hist great post, GDPR is not just about encryption. However as encryption mitigates the risk of infringement of this GDPR it seems like a good quick-win to take on account. On this post we will provide some advices to implement encryption in your Django based site.

During our research on how to encrypt information on a database we found different frameworks available such as:

We chose django-cryptography due to this reasons:

  • Flexibility when you need to work with custom fields
  • Python 3 compatibility
  • Django 1.8+ and Django 2.0 compatibility
  • Ability to choose between different cryptography backends

2. How to try it

In this section we will describe how to encrypt fields on your database. All the code described here is available on a this github repository

First of all, we created an empty project with a :

django-admin startproject django_encrypt_example
django-admin startapp encrypted_app

We then added the encrypted_app application to INSTALLED_APPS on our settings.py

Our next step is to define our example model on encrypted_app/models.py:

Now, we have to create the migration file and run it:

python manage.py makemigrations
python manage.py migrate

We also need to define an Admin configuration as well in order to be able to add instances to our encrypted model, so on encrypted_app/admin.py we add:

If we go to the admin page and add an instance of our recently created model we don’t see anything special, it seems that the data is stored as usual:
Screenshot But if we then query the database with select * from encrypted_app_modelwithsomeencryptedfields we will see that the encrypted_field is stored encrypted in the database:
Screenshot

3. Final considerations about migrations

If you have a database with a column1 that you want to encrypt, maybe it is not the best strategy to directly decorate the existing file with the encrypt decorator. In fact, I tried it and it results on a crash when you list the migrated object. This is because django-cryptography expects the field to be encrypted when it reads it. The best approach here could be something like:

  1. Create an encrypted column2
  2. Create a manual migration that assigns to column2 the values of column1(automatically encrypted)
  3. Remove the column 1 from the database
  4. Rename column2 to column1 again

4. Conclusion

And that’s it, you now should have a Django app with encrypted columns up and running. Happy coding :)