python-3.xdjangodjango-modelsdjango-2.2

Django Model Field for a Secure String


In short: I want to store strings encrypted in the database and decrypt them when i need them. What is the best practice for this?

Context: I am building an application that uses a 3rd party API that requires a login and password. I want to store the credentials that will be used for the 3rd party API in the database as their will be many different credentials. I was looking on the django documentation and on stackoverflow but i only find things that hash passwords.

EDIT: I did some more searching and i realy liked this: https://github.com/georgemarshall/django-cryptography

Anyone some other ideas or opinions on the repository i found?


Solution

  • You should create a custom model field and override the from_db_value() and get_prep_value to encrypted and decrypt the string. You can use many packages to do the encryption algorithm.

    With cryptography you can do something like:

    from django.db.models import CharField
    from cryptography.fernet import Fernet
    from django.conf import settings
    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives import hashes
    from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
    
    class SecureString(CharField):
        """Custom Encrypted Field"""
    
        kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), 
                         length=32, 
                         salt=salt, 
                         iterations=100000, 
                         backend=default_backend())
    
        key = base64.urlsafe_b64encode(kdf.derive(settings.SECRET_KEY))
    
        f = Fernet(key)
    
        def from_db_value(self, value, expression, connection):
            return f.decrypt(value)
    
        def get_prep_value(self, value):
            return f.encrypt(value)
    

    Note: You should abstract the encryption logic for a more optimal solution.