mirror of
https://github.com/wahyd4/links.git
synced 2026-08-09 05:06:16 +10:00
40 lines
1.3 KiB
Python
40 lines
1.3 KiB
Python
import base64
|
|
import hashlib
|
|
|
|
from cryptography.fernet import Fernet
|
|
from django.conf import settings
|
|
from django.db import models
|
|
|
|
|
|
def _get_fernet():
|
|
"""Derive a Fernet key from Django's SECRET_KEY."""
|
|
raw_key = hashlib.sha256(settings.SECRET_KEY.encode()).digest()
|
|
return Fernet(base64.urlsafe_b64encode(raw_key))
|
|
|
|
|
|
class EncryptedCharField(models.TextField):
|
|
"""
|
|
Stores values encrypted at rest using Fernet symmetric encryption.
|
|
The encryption key is derived from Django's SECRET_KEY so no extra
|
|
secrets management is required — if the SECRET_KEY is set, values
|
|
are protected.
|
|
|
|
From the application's perspective this behaves like a plain text field:
|
|
you read/write plaintext; encryption/decryption happens transparently.
|
|
"""
|
|
|
|
def from_db_value(self, value, expression, connection):
|
|
if not value:
|
|
return value
|
|
try:
|
|
return _get_fernet().decrypt(value.encode()).decode()
|
|
except Exception:
|
|
# Gracefully return raw value if decryption fails
|
|
# (e.g. migrating plaintext rows that were saved before encryption)
|
|
return value
|
|
|
|
def get_prep_value(self, value):
|
|
if not value:
|
|
return value
|
|
return _get_fernet().encrypt(value.encode()).decode()
|