django-fernet-encrypted-fields

repository·main·Indexed 40 days ago

https://github.com/jazzband/django-fernet-encrypted-fields

Symmetrically encrypted model fields for Django version 0.4.0. It provides fields such as EncryptedCharField, EncryptedTextField, and EncryptedJSONField to encrypt data at rest using Fernet symmetric encryption. Supports key rotation via SECRET_KEY_FALLBACKS and SALT_KEY settings, utilizing PBKDF2HMAC with SHA256 for key derivation.

Tokens
1.5K
Snippets
8
Records
9
Agent score
50%

What's inside django-fernet-encrypted-fields

  1. Rotate SALT_KEY

    main

    You can rotate salt keys by providing a list to the SALT_KEY setting instead of a single string.

    • The first key in the list is used for all new encryption operations.
    • Decryption attempts will use all keys in the list, in order, until a match is found.

    This allows you to introduce a new key at the head of the list while maintaining access to data encrypted with older keys.

    SALT_KEY = [
        'zyxwvutsrqponmlkjihgfedcba9876543210',  # New key for new data
        '0123456789abcdefghijklmnopqrstuvwxyz'   # Old key for existing data
    ]
  2. Configure and use EncryptedTextField

    main

    To use encrypted fields, you must first define a SALT_KEY in your settings.py. Then, import the appropriate encrypted field class from encrypted_fields.fields in your models.py.

    # settings.py
    SALT_KEY = '0123456789abcdefghijklmnopqrstuvwxyz'
    
    # models.py
    from encrypted_fields.fields import EncryptedTextField
    
    class MyModel(models.Model):
        text_field = EncryptedTextField()
  3. Rotate SECRET_KEY

    main

    To rotate the Django SECRET_KEY without losing access to encrypted data (requires Django >= 4.1), use the SECRET_KEY_FALLBACKS setting.

    1. Set the new value to SECRET_KEY.
    2. Add the old key to the SECRET_KEY_FALLBACKS list.

    Existing encrypted fields will still work using the fallback. To migrate existing records to the new key, iterate through your models and call .save() on each instance.

    # settings.py
    SECRET_KEY = "new-key"
    SECRET_KEY_FALLBACKS = ["old-key"]
    
    # Migration script to update existing records
    for obj in MyModel.objects.all():
        obj.save()
  4. How EncryptedJSONField works

    main

    The EncryptedJSONField provides recursive encryption for JSON data. When saving, it traverses dictionaries and lists, encrypting individual leaf values (strings/scalars) before serializing the entire structure to a JSON string in the database. When retrieving, it parses the JSON and recursively decrypts the values.

    Note that the field stores the encrypted structure as a JSON string in the database, effectively treating the underlying database column as a text-based field.

    # If you save:
    model.metadata = {"user": "alice", "tags": ["admin", "staff"]}
    
    # The database stores a JSON string where "alice", "admin", and "staff" 
    # are individually encrypted Fernet tokens.
  5. Generate a new secret key

    main

    You can use Django's built-in utility to generate a secure key for your settings.

    from django.core.management.utils import get_random_secret_key
    
    new_secret_key = get_random_secret_key()
    print(new_secret_key)
  6. Configure encryption keys and salts

    main

    Encryption keys are derived from Django settings using PBKDF2HMAC. To enable encryption and support key rotation, configure the following settings in your settings.py:

    • SECRET_KEY: The primary secret key used for derivation.
    • SECRET_KEY_FALLBACKS: A list of additional secret keys. This allows for seamless key rotation; the library uses MultiFernet to attempt decryption with all available keys.
    • SALT_KEY: A salt used in the key derivation process. This can be a single string or a list of strings.

    Key derivation uses SHA256 with 100,000 iterations.

    # settings.py
    
    SECRET_KEY = "your-primary-secret-key"
    SECRET_KEY_FALLBACKS = ["old-secret-key-1", "old-secret-key-2"]
    
    # SALT_KEY can be a single value or a list
    SALT_KEY = "a-very-secure-salt"
  7. Available Encrypted Fields

    main

    The package provides several encrypted field types that mirror the APIs of standard Django fields. Available fields include:

    • EncryptedCharField
    • EncryptedTextField
    • EncryptedDateTimeField
    • EncryptedIntegerField
    • EncryptedFloatField
    • EncryptedEmailField
    • EncryptedBooleanField
    • EncryptedJSONField
  8. Use encrypted Django model fields

    main

    The library provides several encrypted field classes that inherit from standard Django fields. These fields automatically encrypt data before saving it to the database and decrypt it when retrieved.

    Available encrypted field types include:

    • EncryptedCharField
    • EncryptedTextField
    • EncryptedDateTimeField
    • EncryptedIntegerField
    • EncryptedDateField
    • EncryptedFloatField
    • EncryptedEmailField
    • EncryptedBooleanField
    • EncryptedJSONField
    from django.db import models
    from encrypted_fields.fields import (
        EncryptedCharField, 
        EncryptedDateTimeField, 
        EncryptedJSONField
    )
    
    class MyModel(models.Model):
        secret_name = EncryptedCharField(max_length=255)
        last_login = EncryptedDateTimeField()
        metadata = EncryptedJSONField()