One way of enhancing the security of a database is by encrypting it. Luckily by utilizing Django, we can do this automatically. We only need the signing and models packages from the core Django packages.
Let's start by importing the required packages:
from django.core import signing
from django.db.models import TextField
First, the signing
is a cryptographic signing package; it allows encrypting and decrypting using the SECRET_KEY
found in settings.py
; more info can be found at the bottom, and we need the TextField
because we will extend the default one with more functionality.
Now let's create and init the new field. I'll name it EncryptedTextField
:
class EncryptedTextField(models.TextField):
def __init__(self, *args, **kwargs):
super(EncryptedTextField, self).__init__(*args, **kwargs)
Now for the encrypting part:
def get_db_prep_save(self, value, connection):
value = super().get_db_prep_value(value, connection)
if value is None:
return value
if len(value) == 0:
return value
return ((signing.dumps(str(value))).encode('utf-8')).decode('utf-8')
The get_db_prep_save
is a function that runs when we try to save data to the database; we are getting the raw data by get_db_prep_value
and then return an encrypted version of it return ((signing.dumps(str(value))).encode('utf-8')).decode('utf-8')
. More info can be found at the bottom.
Now for the decrypting part:
def from_db_value(self, value, *args, **kwargs):
if value is None:
return value
if len(value) == 0:
return value
return signing.loads(value)
The def from_db_value
is a function that runs when we try to get data from the database, value
here represents the encrypted data, so we need to decrypt it, which is done here return signing.loads(value)
. More info can be found at the bottom.
Example of usage:
public_api = EncryptedTextField()
Example of a full code:
from django.db.models import TextField
from django.core import signing
class EncryptedTextField(models.TextField):
def __init__(self, *args, **kwargs):
super(EncryptedTextField, self).__init__(*args, **kwargs)
def get_db_prep_save(self, value, connection):
value = super().get_db_prep_value(value, connection)
if value is None:
return value
if len(value) == 0:
return value
return ((signing.dumps(str(value))).encode('utf-8')).decode('utf-8')
def to_python(self, value):
return value
def from_db_value(self, value, *args, **kwargs):
if value is None:
return value
if len(value) == 0:
return value
return signing.loads(value)
Links to more info:
The
signing
package: https://docs.djangoproject.com/en/4.1/topics/signing/The
get_db_prep_save
function:
https://docs.djangoproject.com/en/4.1/ref/models/fields/#django.db.models.Field.get_db_prep_saveThe
from_db_value
function:
https://docs.djangoproject.com/en/4.1/ref/models/fields/#django.db.models.Field.from_db_value
Top comments (0)