Pankaj Jackson
Pankaj Jackson

Reputation: 3751

How to encrypt TextField before saving in database

Here I am Trying to create Model where i can save Password, here my model:

class Server(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=20, null=True)
    hostname = models.CharField(max_length=50, null=True, blank=True)
    ip = models.GenericIPAddressField()
    ip2 = models.GenericIPAddressField(null=True, blank=True)
    user_name = models.CharField(max_length=20, null=True)
    password = models.TextField(max_length=500, null=True, blank=True)
    ssh_key = models.FileField(null=True, blank=True, upload_to='Keys/')

till now i read lot of blogs and posts but i haven't found any good way to save encrypted text in database

i was trying this method but it is also not working for me please check my View.py below,

from cryptography.fernet import Fernet
class HostCreate(CreateView):
    model = Server
    template_name = 'inventory/host_create.html'
    form_class = HostForm

    # after getting POST data of fields (name, hostname, ip, pass, key) adding user and saving
    def form_valid(self, form):
        host = form.save(commit=False)
        host.user = User.objects.get(pk=self.request.user.pk)
        host.password = self.ecrypt(host.password)
        host.save()
        return redirect('inventory:hosts')

    def ecrypt(self, password): # need password and return cipher password
        key = 'wgjSSyfVKgz0EjyTilqeJSaANLDu7TzHKdpAXUeZPbM='
        cipher_suite = Fernet(key)
        cipher_text = cipher_suite.encrypt(password)
        return cipher_text 

here i am getting error,

Exception Type:     TypeError
Exception Value:    data must be bytes.
Exception Location:     /usr/lib64/python2.7/site-packages/cryptography/fernet.py in _encrypt_from_parts, line 55

Is there any builtin django functionality for password field?

Upvotes: 2

Views: 10260

Answers (4)

CharlesB
CharlesB

Reputation: 90346

You can use the django-fernet-fields library, which defines EncryptedXXXField for you:

from django.db import models
from fernet_fields import EncryptedTextField


class MyModel(models.Model):
    name = EncryptedTextField()

The values are saved with symmetric encryption, and by default uses SECRET_KEY as en encryption key, so all you need to do is keep your SECRET_KEY constant over time.

Upvotes: 0

Drg
Drg

Reputation: 11

For the password field, Django uses its own hashing. You can change it though.

There are a few encryption methods in Django. You can use them like AES. It can be imported from crypto cipher.

Otherwise you can use the default Django Signer.

Upvotes: 1

Muhammad Hassan
Muhammad Hassan

Reputation: 14391

You can do it in two possible ways.

  1. Write custom save method for your model like this

    class Server(models.Model):
        user = models.ForeignKey(User, on_delete=models.CASCADE)
        name = models.CharField(max_length=20, null=True)
        hostname = models.CharField(max_length=50, null=True, blank=True)
        ip = models.GenericIPAddressField()
        ip2 = models.GenericIPAddressField(null=True, blank=True)
        user_name = models.CharField(max_length=20, null=True)
        password = models.TextField(max_length=500, null=True, blank=True)
        ssh_key = models.FileField(null=True, blank=True, upload_to='Keys/')
    
        def save(self, *args, **kwargs):
            if not self.pk:
                # encrypt_field_value_here
            super(Server, self).save(*args, **kwargs)
    
  2. You can use custom model fields. You can get documentation on this from here. Also check BaseEncryptedField from here.

You can also use this package.

Upvotes: 6

Pankaj Jackson
Pankaj Jackson

Reputation: 3751

I solved it by using django-encrypted-fields Packages Steps are :

on Project Root directory open terminal and Execute commands.

  1. Install Package django-encrypted-fields

    $ pip install django-encrypted-fields
    
  2. Create a basic keyczar keyset. AES-256 in this case.

    $ mkdir fieldkeys
    $ keyczart create --location=fieldkeys --purpose=crypt
    $ keyczart addkey --location=fieldkeys --status=primary --size=256
    
  3. Add settings In your settings.py

    ENCRYPTED_FIELDS_KEYDIR = os.path.join(BASE_DIR, 'fieldkeys')
    
  4. Now in models.py

    from django.db import models
    import encrypted_fields
    class Server(models.Model):
        password = encrypted_fields.EncryptedCharField(max_length=500)
    

for more details please visit here

hope this will help someone in future

Upvotes: 0

Related Questions