Field with encryption/decryption on save/read for use in Peewee ORM models
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
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()
Key Derivation Example
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)