Skip to content

Commit

Permalink
Finished release 0.1.6.
Browse files Browse the repository at this point in the history
  • Loading branch information
erikvw committed Jun 12, 2016
2 parents bd3382d + 51f7883 commit 3adff6b
Show file tree
Hide file tree
Showing 44 changed files with 1,138 additions and 804 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,3 +1,4 @@
.cache
*.py[cod]
*.sh
.project
Expand Down
14 changes: 9 additions & 5 deletions README.md
Expand Up @@ -18,11 +18,11 @@ For example:

first_name = FirstnameField(
verbose_name="First Name")

identity = IdentityField(
verbose_name="Identity",
unique=True)

comment = EncryptedTextField(
max_length=500)

Expand All @@ -40,10 +40,10 @@ Add to INSTALLED_APPS:
)

Add KEY_PATH to the folder in settings:

# folder where the encryption keys are stored
KEY_PATH = '/Volumes/secure_drive/keys')

Add KEY_PREFIX (optional, the default is "_user_"):

# optional filename prefix for encryption keys files:
Expand Down Expand Up @@ -82,11 +82,15 @@ Advantages
Disadvantages
-------------

- Limited support for lookup types. The "query value" is the hash not the decrypted secret, so Django lookups like ['startswith', 'istartswith', 'endswith', 'iendswith', 'contains', 'icontains', 'iexact'] are not supported.
- Limited support for lookup types. The "query value" is the hash not the decrypted secret, so Django lookups like ['startswith', 'istartswith', 'endswith', 'iendswith', 'contains', 'icontains', 'iexact'] are not supported.
- Hashing with a secret may be considered less secure than just a "secret". You decide what your requirements are. For systems that collect PII in fields classes from _django-crypto-fields_, we take all the basic security precautions: OS and application-level password protection, Full-Drive encryption, physical security and so on.

Other encrypted field modules are available if you just want to use encrypted field classes in Django models and do not need unique constraints nor plan to join tables on encrypted fields for analysis.

### Installation Issues
`django-crypto-fields` requires `pycrypto`. If `pycrypto` has trouble installing try:

CFLAGS="-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -I/usr/local/include" LDFLAGS="-L/usr/local/lib" pip install pycrypto

Contribute
----------
Expand Down
39 changes: 39 additions & 0 deletions django_crypto_fields/admin.py
@@ -0,0 +1,39 @@
from django.apps import apps as django_apps
from django.contrib import admin
from django.contrib.admin import AdminSite
# from django_crypto_fields.models import Crypt


Crypt = django_apps.get_model(*django_apps.get_app_config('django_crypto_fields').model)


class CryptoFieldsAdminSite(AdminSite):
"""
For example:
add to urls:
url(r'^admin/', encryption_admin.urls),
then:
>>> reverse('encryption_admin:django_crypto_fields_crypt_add')
'/admin/django_crypto_fields/crypt/add/'
"""
site_header = 'Data Encryption Administration'
site_title = 'Data Encryption Administration'
index_title = 'Data Encryption'
site_url = '/crypto_fields/'
crypto_fields_admin = CryptoFieldsAdminSite(name='encryption_admin')


@admin.register(Crypt, site=crypto_fields_admin)
class CryptAdmin(admin.ModelAdmin):

date_hierarchy = 'modified'

fields = sorted([field.name for field in Crypt._meta.fields])

readonly_fields = [field.name for field in Crypt._meta.fields]

list_display = ('algorithm', 'hash', 'modified', 'hostname_modified')

list_filter = ('algorithm', 'modified', 'hostname_modified')

search_fields = ('hash', )
41 changes: 39 additions & 2 deletions django_crypto_fields/apps.py
@@ -1,6 +1,43 @@
import sys

from django.apps import AppConfig

from django.core.management.color import color_style


class DjangoCryptoFieldsError(Exception):
pass


class DjangoCryptoFieldsAppConfig(AppConfig):
name = 'django_crypto_fields'
verbose_name = "Data Encryption"
encryption_keys = None
model = ('django_crypto_fields', 'crypt')
crypt_model_using = 'default' # change if using more than one database and not 'default'.

def __init__(self, app_label, model_name):
"""Placed here instead of `ready()`. For models to load correctly that use
field classes from this module the keys need to be loaded before models."""
super(DjangoCryptoFieldsAppConfig, self).__init__(app_label, model_name)
from django_crypto_fields.keys import Keys
keys = Keys()
if not self.encryption_keys:
style = color_style()
sys.stdout.write('Loading {} ...\n'.format(self.verbose_name))
if not keys.key_files_exist():
sys.stdout.write(style.NOTICE('Warning: {} failed to load encryption keys.\n'.format(
self.verbose_name)))
sys.stdout.write('Confirm that settings.KEY_PATH points to the correct folder.\n')
sys.stdout.write('Loading the wrong encryption keys can corrupt sensitive data.\n')
sys.stdout.write('If this is your first time loading the project, '
'new keys will be generated\n')
sys.stdout.write('and placed in the settings.KEY_PATH folder.\n')
keys.create_keys()
keys.load_keys()
self.encryption_keys = keys


class DjangoCryptoFieldsConfig(AppConfig):
class TestDjangoCryptoFieldsApp(DjangoCryptoFieldsAppConfig):
name = 'django_crypto_fields'
verbose_name = "django-crypto-fields"
model = ('example', 'crypt')
4 changes: 0 additions & 4 deletions django_crypto_fields/classes/__init__.py

This file was deleted.

80 changes: 0 additions & 80 deletions django_crypto_fields/classes/cryptor.py

This file was deleted.

84 changes: 0 additions & 84 deletions django_crypto_fields/classes/keys.py

This file was deleted.

54 changes: 13 additions & 41 deletions django_crypto_fields/constants.py
@@ -1,46 +1,18 @@
import os
from django.core.management.color import color_style

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
style = color_style()


RSA_KEY_SIZE = 2048
AES = 'aes'
CIPHER_BUFFER_SIZE = 10
CIPHER_PREFIX = 'enc2:::'
ENCODING = 'utf-8'
HASH_ALGORITHM = 'sha256'
HASH_ROUNDS = 100000
HASH_PREFIX = 'enc1:::'
CIPHER_PREFIX = 'enc2:::'
CIPHER_BUFFER_SIZE = 10

try:
KEY_PREFIX = settings.KEY_PREFIX
except (ImproperlyConfigured, AttributeError) as e:
KEY_PREFIX = 'user'

try:
KEY_PATH = settings.KEY_PATH
except (ImproperlyConfigured, AttributeError) as e:
KEY_PATH = settings.BASE_DIR
KEY_PREFIX = 'test'
print('Warning! Not ready for production. {}. Setting KEY_PATH to {} for testing purposes.'.format(e, KEY_PATH))

KEY_FILENAMES = {
# algorithm : {mode: {key:path}}
'rsa': {
'restricted': {
'public': os.path.join(KEY_PATH, KEY_PREFIX + '-rsa-restricted-public.pem'),
'private': os.path.join(KEY_PATH, KEY_PREFIX + '-rsa-restricted-private.pem')},
'local': {
'public': os.path.join(KEY_PATH, KEY_PREFIX + '-rsa-local-public.pem'),
'private': os.path.join(KEY_PATH, KEY_PREFIX + '-rsa-local-private.pem')}},
'aes': {
'local': {
'private': os.path.join(KEY_PATH, KEY_PREFIX + '-aes-local.key')},
'restricted': {
'private': os.path.join(KEY_PATH, KEY_PREFIX + '-aes-restricted.key')}},
'salt': {
'local': {
'private': os.path.join(KEY_PATH, KEY_PREFIX + '-salt-local.key')},
'restricted': {
'private': os.path.join(KEY_PATH, KEY_PREFIX + '-salt-restricted.key')}},
}
HASH_ROUNDS = 100000
LOCAL_MODE = 'local'
PRIVATE = 'private'
PUBLIC = 'public'
RSA = 'rsa'
RSA_KEY_SIZE = 2048
SALT = 'salt'
RESTRICTED_MODE = 'restricted'

0 comments on commit 3adff6b

Please sign in to comment.