Pinakes uses encryption to protect sensitive data stored in the database.
Pinakes uses Fernet algorithm provided by the cryptography package for authenticated encryption (AE) of the sensitive data stored in the database.
Fernet uses Encrypt-then-MAC (EtM) scheme based on AES-128-CBC
for encryption with PKCS7
padding
and HMAC-SHA256
for authentication.
Pinakes uses PINAKES_DB_ENCRYPTION_KEYS
environment variable to set encryption keys for the application.
The environment variable is a colon (:
) separated string of one or more encryption keys.
The first key is a primary key used for decryption and encryption of saved data and the following keys are
secondary keys, used for decryption of existing data only.
PINAKES_DB_ENCRYPTION_KEYS={PRIMARY_KEY}[(:{SECONDARY_KEY})...]
Before running the application you need to generate a database encryption key. It is a URL-safe base64 encoded 32-byte key. Pinakes provides a convenient tool to generate one:
$ python manage.py generate_encryption_key
5DU16...
Copy this key and use it to set PINAKES_DB_ENCRYPTION_KEYS
environment variable.
Or you can generate it programmatically:
Python:
from cryptography.fernet import Fernet
key = Fernet.generate_key()
Shell:
$ head -c32 /dev/urandom | base64 | tr '+/' '-_'
In some cases you may want to generate a new encryption key and replace with it the old one.
First generate a new key:
$ python manage.py generate_encryption_key
Then amend your application configuration. Put the new key to the front of
PINAKES_DB_ENCRYPTION_KEYS
environment variable and restart or redeploy the application:
PINAKES_DB_ENCRYPTION_KEYS={NEW_KEY}:{OLD_KEY}
Now any new data or updates to existing data are encrypted with the new key when saved to the database. An old key is still used for existing data that is read from the database.
To re-encrypt all relevant database records with the new (primary) encryption key run:
$ python manage.py reencrypt_database
Now any secondary encryption keys may be deleted.