Encrypted field for Peewee ORM models to save data in DB in encrypted form.
Data stored in DataBase as Fernet tokens. After you define an encryption key all cryptography will be performed transparently for your application.
Uses simple fernet implementation https://github.com/heroku/fernet-py
Idea caught from SQLAlchemy's EncryptedType.
A fernet-py package can use Pycrypto or M2Crypto as backend (details). Same belongs to this module due to its dependency from fernet-py. Note that pip
uses Pycrypto as a default dependency when install fernet-py.
Length of entire key is 32 bytes, 16 bytes per both signing and encryption keys, as stated in specification.
You have to set key
as a property of appropriate EncryptedField
. You need to set this property once per Model
per Model
's Field
.
If you attempt to set key
property for a Field
whose key
already has been set, exception EncryptedField.KeyAlreadyExists
will be raised. To change the key
on the fly you have to explictly perform del SomeEncryptedField.key
and then set this property to desired value again.
pip install peewee_encrypted_field
or, if you downloaded source,
python setup.py install
At first, import module
from peewee import *
from peewee_encrypted_field import EncryptedField
Then, define the model with EncryptedField
class SecureTable(BaseModel):
sensitive_data = EncryptedField()
class Meta:
db_table = 'SecureTable'
After, configure field's encryption key
SecureTable.sensitive_data.key = key_derivation_fn() # a hypotetical key derivation
# function returning 32 byte key
Finally, save and retrieve data in a Peewee's usual manner
new_secret = SecureTable(sensitive_data='My New BIG Secret')
new_secret.save()
Example Key Derivation Function baded on Pycrypto module.
Please take look at this Gist - it can contain more actual version of code below.
from binascii import unhexlify
from functools import partial
from Crypto.Protocol import KDF
from Crypto.Hash import SHA512, HMAC
_SALT = unhexlify('48B755AB80CD1C3DA61182D3DCD2E3A2CA869B783618FF6551FB4B0CDC3B8066') # some salt
_KEY_LENGTH = 32
key_derivation_fn = partial(
KDF.PBKDF2,
salt=_SALT,
dkLen=_KEY_LENGTH,
count=5000,
prf=lambda p,s: HMAC.new(p,s,SHA512).digest()
)
# KDF usage
SecureTable.sensitive_data.key = key_derivation_fn(text_password)