HH/apps/core/encryption.py
2026-04-09 13:46:34 +03:00

72 lines
1.8 KiB
Python

import base64
import hashlib
from cryptography.fernet import Fernet
from django.conf import settings
from django.db import models
def _get_fernet() -> Fernet:
key = hashlib.sha256(settings.SECRET_KEY.encode()).digest()
return Fernet(base64.urlsafe_b64encode(key))
def encrypt_value(plaintext: str) -> str:
if not plaintext:
return ""
f = _get_fernet()
return f.encrypt(plaintext.encode()).decode()
def decrypt_value(ciphertext: str) -> str:
if not ciphertext:
return ""
f = _get_fernet()
return f.decrypt(ciphertext.encode()).decode()
def compute_national_id_hash(value: str) -> str:
if not value:
return ""
salt = settings.SECRET_KEY.encode()
return hashlib.sha256(salt + value.strip().encode()).hexdigest()
def mask_national_id(value: str) -> str:
if not value:
return ""
value = value.strip()
if len(value) <= 4:
return "*" * len(value)
return "*" * (len(value) - 4) + value[-4:]
class EncryptedCharField(models.CharField):
def get_prep_value(self, value):
if not value:
return value
return encrypt_value(str(value))
def from_db_value(self, value, expression, connection):
if not value:
return value
try:
return decrypt_value(value)
except Exception:
return value
def to_python(self, value):
if not value:
return value
if isinstance(value, str):
try:
return decrypt_value(value)
except Exception:
return value
return value
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
path = "apps.core.encryption.EncryptedCharField"
return name, path, args, kwargs