Custom model field to support two ways encryption. The key is provided in the app settings.py file. It should be at least 32 chars.
usage
Assuming that you placed the new code into fields.py
from app.fields import EncyptedField
class Account(models.Model):
password = EncryptedField()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | # -*- coding: utf-8 -*-
import types
import base64
from Crypto import Random
from Crypto.Cipher import AES
from django.db import models
from app.settings import FIELD_ENCRYPTION_KEY
class EncryptedField(models.Field):
__metaclass__ = models.SubfieldBase
def __init__(self, *args, **kwargs):
self.prefix = kwargs.pop('prefix', '_')
super(EncryptedField, self).__init__(*args, **kwargs)
def get_internal_type(self):
return 'TextField'
def to_python(self, value):
if value is None or not isinstance(value, types.StringTypes):
return value
if self.is_encrypted(value):
value = value[len(self.prefix):] # cut prefix
value = base64.b64decode(value)
iv, encrypted = value[:AES.block_size], value[AES.block_size:] # extract iv
crypto = AES.new(FIELD_ENCRYPTION_KEY[:32], AES.MODE_CBC, iv)
raw_decrypted = crypto.decrypt(encrypted)
value = raw_decrypted.rstrip("\0").decode('unicode_escape')
return value
def get_db_prep_value(self, value, connection, prepared=False):
if not prepared:
iv = Random.new().read(AES.block_size)
crypto = AES.new(FIELD_ENCRYPTION_KEY[:32], AES.MODE_CBC, iv)
if isinstance(value, types.StringTypes):
value = value.encode('unicode_escape')
value = value.encode('ascii')
else:
value = str(value)
tag_value = (value + (AES.block_size - len(value) % AES.block_size) * "\0")
value = self.prefix + base64.b64encode(iv + crypto.encrypt(tag_value))
return value
def is_encrypted(self, value):
"""checks if a string is encrypted against a static predefined prefix"""
if self.prefix and value.startswith(self.prefix):
return True
else:
return False
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
Please login first before commenting.