Code Monkey home page Code Monkey logo

django-encrypted-fields's Introduction

Build Status Pypi Package

Django Encrypted Fields

This is a collection of Django Model Field classes that are encrypted using Keyczar.

About Keyczar

Keyczar is a crypto library that exposes a simple API by letting the user set things like the algorithm and key size right in the keyfile. It also provides for things like expiring old keys and cycling in new ones.

Getting Started

$ pip install django-encrypted-fields

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

In your settings.py

ENCRYPTED_FIELDS_KEYDIR = '/path/to/fieldkeys'

Then, in models.py

from encrypted_fields import EncryptedTextField

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

Use your model as normal and your data will be encrypted in the database.

Warning: Once the data is encrypted, it can no longer to used to query or sort. In SQL, these will all look like text fields with random noise in them (which is what you want).

Available Fields

Currently build in and unit-tested fields. They have the same APIs as their non-encrypted counterparts.

  • EncryptedCharField
  • EncryptedTextField
  • EncryptedDateTimeField
  • EncryptedIntegerField
  • EncryptedFloatField
  • EncryptedEmailField
  • EncryptedBooleanField

Encrypt All The Fields!

Making new fields is easy! Django Encrypted Fields uses a handy mixin to make upgrading pre-existing fields quite easy.

from django.db import models
from encrypted_fields import EncryptedFieldMixin

class EncryptedIPAddressField(EncryptedFieldMixin, models.IPAddressField):
    pass

Please report an issues you encounter when trying this, since I've only tested it with the fields above.

django-encrypted-fields's People

Contributors

defrex avatar ebpmp avatar gimbo avatar obrienmd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-encrypted-fields's Issues

Filter on encrypted fields

Filter on EncryptedCharField is not working... It is returning None in both the cases

  1. when i paste encrypted value from DB.
  2. or when i paste decrypted value.

Error on save

I am getting the following error when trying to do a create

[Wed Aug 24 16:18:39 2016] [error]   File "/home/vagrant/.virtualenvs/turktools/lib/python3.4/site-packages/encrypted_fields/fields.py", line 163, in to_python
[Wed Aug 24 16:18:39 2016] [error]     if value is None or not isinstance(value, types.StringTypes):
[Wed Aug 24 16:18:39 2016] [error] AttributeError: 'module' object has no attribute 'StringTypes'

Full trace:
http://dpaste.com/0SWTFF9

with my models.py setup:

from django.db import models
from django.contrib.auth.models import User
from encrypted_fields import EncryptedCharField


class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    aws_key = EncryptedCharField(max_length=50)
    aws_secret_key = EncryptedCharField(max_length=50)

Any ideas?

[UPDATE:] I added a pull request: #23

Encrypting Previously entered data

Thanks for making this. Worked like a charm, but I noticed an unexpected issue when i started using the app.
I had a previously unencrypted CharField of first_name and last_name'
I installed django-encrypted field and updated my model using the EncryptedCharField. When I enter new data, everything appears as I expected: The view shows me the unencrypted first_name and last_name while the database shows the fields encrypted.

However, with the data that was already entered, the view shows the encrypted fields as they appear on the database - basically gibberish. Is there anything that can be done about this? I'm working with a local version, but want to update the deployed version with the encrypted fields, but I'm a bit concerned that I would freak out users because of the above issue.

char field max length

Trying to make a migration and having an issue:

SystemCheckError: System check identified some issues:

ERRORS:
app.Server.password: (fields.E120) CharFields must define a 'max_length' attribute.

I saw there was a variable for "enforce_max_length", however that doesn't appear to get rid of the error. It still appears to complain if that is there. What is the proper way to handle this, enforce_max_length + max_length or just max_length?

Not able to work with django-rest

Hi, I am trying to encrypt the fields,

class BankDetails(models.Model):
    id              = models.AutoField(primary_key=True)
    bank_name       = EncryptedTextField()
    account_number  = EncryptedIntegerField()
    ifsc_code       = EncryptedIntegerField() 

I am using rest framework also, When I try to access the rest api, it throws an error TextField

Request Method: GET
Request URL: http://localhost.com:8000/bankdetails/

Django Version: 1.7.4
Python Version: 2.7.9
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'rest_framework',
 'rest_framework.authtoken',
 'app',
 'djcelery',
 'kombu.transport.django')
Installed Middleware:
(
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware')


Traceback:
File "C:\Users\YuO\project\www\lib\site-packages\django-1.7.4-py2.7.egg\django\core\handlers\base.py" in get_response
  111.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\YuO\project\www\lib\site-packages\django-1.7.4-py2.7.egg\django\views\decorators\csrf.py" in wrapped_view
  57.         return view_func(*args, **kwargs)
File "C:\Users\YuO\project\www\lib\site-packages\django-1.7.4-py2.7.egg\django\views\generic\base.py" in view
  69.             return self.dispatch(request, *args, **kwargs)
File "C:\Users\YuO\project\www\lib\site-packages\djangorestframework-3.0.5-py2.7.egg\rest_framework\views.py" in dispatch
  407.             response = self.handle_exception(exc)
File "C:\Users\YuO\project\www\lib\site-packages\djangorestframework-3.0.5-py2.7.egg\rest_framework\views.py" in dispatch
  404.             response = handler(request, *args, **kwargs)
File "C:\Users\YuO\project\www\lib\site-packages\djangorestframework-3.0.5-py2.7.egg\rest_framework\generics.py" in get
  311.         return self.list(request, *args, **kwargs)
File "C:\Users\YuO\project\www\lib\site-packages\djangorestframework-3.0.5-py2.7.egg\rest_framework\mixins.py" in list
  46.         return Response(serializer.data)
File "C:\Users\YuO\project\www\lib\site-packages\djangorestframework-3.0.5-py2.7.egg\rest_framework\serializers.py" in data
  615.         ret = super(ListSerializer, self).data
File "C:\Users\YuO\project\www\lib\site-packages\djangorestframework-3.0.5-py2.7.egg\rest_framework\serializers.py" in data
  212.                 self._data = self.to_representation(self.instance)
File "C:\Users\YuO\project\www\lib\site-packages\djangorestframework-3.0.5-py2.7.egg\rest_framework\serializers.py" in to_representation
  565.             self.child.to_representation(item) for item in iterable
File "C:\Users\YuO\project\www\lib\site-packages\djangorestframework-3.0.5-py2.7.egg\rest_framework\serializers.py" in to_representation
  419.         fields = [field for field in self.fields.values() if not field.write_only]
File "C:\Users\YuO\project\www\lib\site-packages\djangorestframework-3.0.5-py2.7.egg\rest_framework\serializers.py" in fields
  312.             for key, value in self.get_fields().items():
File "C:\Users\YuO\project\www\lib\site-packages\djangorestframework-3.0.5-py2.7.egg\rest_framework\serializers.py" in get_fields
  1006.                 kwargs = get_field_kwargs(field_name, model_field)
File "C:\Users\YuO\project\www\lib\site-packages\djangorestframework-3.0.5-py2.7.egg\rest_framework\utils\field_mapping.py" in get_field_kwargs
  70.     validator_kwarg = list(model_field.validators)
File "C:\Users\YuO\project\www\lib\site-packages\django-1.7.4-py2.7.egg\django\utils\functional.py" in __get__
  55.         res = instance.__dict__[self.func.__name__] = self.func(instance)
File "C:\Users\YuO\project\www\lib\site-packages\django-1.7.4-py2.7.egg\django\db\models\fields\__init__.py" in validators
  1590.         min_value, max_value = connection.ops.integer_field_range(internal_type)
File "C:\Users\YuO\project\www\lib\site-packages\django-1.7.4-py2.7.egg\django\db\backends\__init__.py" in integer_field_range
  1334.         return self.integer_field_ranges[internal_type]

Exception Type: KeyError at /bankdetails/
Exception Value: 'TextField'

Way to store key in settings file

I think it would be nice for ease-of-use to have a key available as a settings-variable. Maybe the SECRET_KEY could be the default encrypter, but you could also have an ENCRYPTION_KEY variable as well.

That would be helpful for deployment, because you could then load these keys through environment variables. I'd rather not check my keys into version control, and deploying to something like AWS lambda is tough when it relies on your filesystem.

Less of an issue and more of a feature request. It goes without saying, but it's a great library.

ValueError: zero length field name in format

Getting error:
File "/home/idbill/workspace/OPT/venv/pyvenv/lib/python2.6/site-packages/django/db/models/sql/compiler.py", line 979, in as_sql
val = field.get_db_prep_save(val, connection=self.connection)
File "/home/idbill/workspace/OPT/venv/pyvenv/lib/python2.6/site-packages/django/db/models/fields/init.py", line 304, in get_db_prep_save
prepared=False)
File "/home/idbill/workspace/OPT/venv/pyvenv/lib/python2.6/site-packages/encrypted_fields/fields.py", line 194, in get_db_prep_value
len(value),
ValueError: zero length field name in format

Appears the following:
'Field {} max_length={} encrypted_len={}'.format(
self.name,
self.max_length,
len(value),

needs to be:
'Field {0} max_length={1} encrypted_len={2}'.format(
self.name,
self.max_length,
len(value),

as per:
http://stackoverflow.com/questions/20941386/django-manage-py-returns-valueerror-zero-length-field-name-in-format

fields.py

I think in fields.py you want it to say

self._crypter = keyczar.Crypter.Read(keyname)

otherwise this does not make sense

def crypter(self):
    return self._crypter

Using private + public different servers

Hi There,

I have a Django project and I am using the encrypted field.

What I liked to do is only using encryption in his project. I did that by setting ENCRYPTED_FIELD_MODE = 'ENCRYPT'

This way there's no possibility to decrypt the encrypted value.

Step 2 is to decrypt the value from another project. At this point I'm stuck.

I'd like to decrypt the encrypted value from another server by using the private key. Can anyone explain me how I can do that?

I'm kinda new in the whole encrypting world especially using public and private keys.

I know there is a private and a public key. How can I save the private key on another server and use it to decrypt encrypted values?

Greetz, Nelson Varela.Using private + public different servers

Incorrect padding error

I have an EncryptedCharField, max length is 64. If I try to set it to 'ElderslooŰŰŰ', I get Incorrect padding error. But if I set it to 'ElderslooŰŰŰŰ' (one Ű more) then it's ok. It can be invoked simply in django admin.
I looked around in the code (fields.py):

def to_python(self, value):
        if value is None or not isinstance(value, str):
            return value

        if self.prefix and value.startswith(self.prefix):
            value = value[len(self.prefix):]

        try:
            value = self.crypter().decrypt(value)
            #value = value.decode('unicode_escape')
        except keyczar.errors.KeyczarError:
            pass
        except UnicodeEncodeError:
            pass

        return super(EncryptedFieldMixin, self).to_python(value)

to_python is called either from 'from_db_value', or from 'clean'. When it gets called from 'clean' the value is not encoded at all, so there is no reason to call 'value = self.crypter().decrypt(value)'. I'm not familiar with django forms code, so I can't judge why it works this way. Since decryption is not needed, silencing the exception works fine, like this way:

   try:
        value = self.crypter().decrypt(value)
        #value = value.decode('unicode_escape')
    except keyczar.errors.KeyczarError:
        pass
    except UnicodeEncodeError:
        pass
    except binascii.Error:
        pass

I use django-encrypted-fields-python3==1.1.3 and django 1.8.

`get_internal_type` for EncryptedIntegerField (django 1.7)

Why get_internal_type is also TextField for EncryptedIntegerField?
When it cames to django validation, django.db.backends.BaseDatabaseOperations#integer_field_range fails, because there are no TextField in self.integer_field_ranges.

I got this problem in django 1.7.

UPD: I understood why, because after encryption it became text.
But before it will be saved in DB, it must pass validation.

location of fieldkeys

ENCRYPTED_FIELDS_KEYDIR = '/path/to/fieldkeys'

Is this relative to my project folder?

so / would be considered the top of my project folder.

Make a query over encrypted field

Hello, I'm using your library django encrypted fields and I have a problem when I make a query on the encrypted field. I'm using myModel.objects.filter(names__istartswith = mysearch) and django shows me the result decrypted, but the search is done over the encrypted text, for example: I search names with "A" and it shows me: Roberto... because its encrypted value is AB59cOgUT1lf.............. on my database.

Is there any command I can use to solve this issue? or any way you can suggest me so I can decrypt the field before doing the search?

Consistent encryption output, possible?

Hi there,

When I am encrypting a certain value, keyczar keeps generating a different output.

>>> crypter = Crypter.Read(settings.ENCRYPTED_FIELDS_KEYDIR)
>>> crypter.Encrypt('fooo')
'ALDUpBUMjbaF-cQ7Eq9MTaFASmg1fC5SEgdqtBxcHxNsY_H0gYKAB_x-dT-_2K_f_AqW4fpCsgdl'
>>> crypter.Encrypt('fooo')
'ALDUpBVfCJcWvZ9sEfjJpQyWHvnJDeyii_LDSr93G9FqM0QR1-5p_w3uinNwI4OxYJYAi-9SeeJY'

This is of course very secure, but I am wondering if it's possible to make it output the same cipher text the same for every time I call it? This because I am trying to use your fields in combination with Django's custom user model. This now fails because the stored value never matches the generated one.

New release with SubFieldBase fix?

I'm getting deprecation warnings that appear to originate with v1.1.2 of django-encrypted-fields.

This appears to be fixed in trunk:
ba29585

Any idea when 1.1.3 will be out? Thanks!

Bug with unicode

There is bug in keychar, when you try decrypt unicode (you get empty string). I'm bypased it by adding:

value = value.encode('unicode_escape') in get_prep_value. And in to python: value.decode('unicode_escape').

EncryptedDecimalField Django 1.7

Hi!
I've created my custom EncryptedDecimalField following your readme, so in my utils.py file I've wrote this:

from django.db import models
from encrypted_fields import EncryptedFieldMixin

class EncryptedDecimalField(EncryptedFieldMixin, models.DecimalField):
    pass

Then in my model I've declared an original DecimalField as EncryptedDecimalField but values in db seems not changes. What's going wrong in my code?
Thanks in advance!

Not maintained information

Hello,

you mentioned in #27 that you stopped working on this project. Would you mind to write a hint in the readme that this project is currently not maintained? I think it's really important to inform people about this, because it's security related.

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.