Encrypted fields in Python/Django with Keyczar
In some cases, you will be required to encrypt sensitive data in your database, to avoid plain reading in the event of your database got compromised. Though, the security will be as secured as the location of your encryption key, so make the location and the mean to access it are also as secured as possible.
I will be using Keyczar to handle encryption and key generation, which must be installed first as follows:
$ pip install python-keyczar
The encrypted fields will require a keyset, which is a set of keys inside a folder generated by Keyczar. Now, the Python command use may not be so explicit in the documentation, so I will describe how I got it work.
Once Keyczar is installed, you will find
keyczart.py in the package which is the Keyczar Tool for Python. We will use it in the following way, in the terminal, to generate both our keyset and keys. We want to create a symmetric crypting key (--purpose=crypt), in a folder called 'keyset' (--location=keyset). The name parameter is optional, but useful if you have multiple keysets (--name=myproject).
Create your 'keyset' folder and run the following command in the Python shell:
>>> import keyczar >>> from keyczar import keyczart >>> keyczart.main(['create','--location=keyset','--purpose=crypt','--name=myproject'])
The command will create a `meta` file which is detailing the kind of keyset to be generated.
Now to actually create our key:
>>> keyczart.main(['addkey','--location=keyset' ,'--status=primary'])
Each key in your keyset will numbered incrementally, as you can have multiple keys, while only one can be primary (the active use for encryption).
All Keyczar documentation can be find in the following PDF: Download Keyczar documentation
Once our keyset is ready, let's look at the field implementation.
Django encrypted fields
For the fields, I use the encrypted fields from the django-extensions package (available on Github).
I have copied the encrypted fields file into my admin tools package for ease of access, and here's an example use of the EncryptedCharField:
from django.db import models from admin_tools.util.fields import EncryptedCharField class DataModel(models.Model): sensitive_field = EncryptedCharField(max_length=100)
The encrypted field will look up into your settings to find the keyset folder location, so you will need to set it as follows in
ENCRYPTED_FIELD_KEYS_DIR = os.path.join(PROJECT_DIR, '../../keyset/')
Now every time you save those fields, it will be encrypted in the database, they decrypted at read time. Make sure you create a unique keyset on the server the site will be hosted on, so I can't be find anywhere else.