This commit is contained in:
Iliyan Angelov
2025-11-26 22:32:20 +02:00
commit ed94dd22dd
150 changed files with 14058 additions and 0 deletions

134
accounts/security.py Normal file
View File

@@ -0,0 +1,134 @@
"""
Security utilities for encryption and data protection.
"""
from cryptography.fernet import Fernet
from django.conf import settings
import base64
import hashlib
import os
class DataEncryption:
"""
Encrypt/decrypt sensitive data.
"""
@staticmethod
def get_encryption_key():
"""Get or generate encryption key."""
key = getattr(settings, 'ENCRYPTION_KEY', None)
if not key:
# Generate a key (in production, this should be in environment)
key = Fernet.generate_key()
elif isinstance(key, str):
key = key.encode()
return key
@staticmethod
def encrypt(data):
"""Encrypt sensitive data."""
if not data:
return data
try:
key = DataEncryption.get_encryption_key()
f = Fernet(key)
encrypted = f.encrypt(data.encode() if isinstance(data, str) else data)
return base64.urlsafe_b64encode(encrypted).decode()
except Exception:
return data # Return original if encryption fails
@staticmethod
def decrypt(encrypted_data):
"""Decrypt sensitive data."""
if not encrypted_data:
return encrypted_data
try:
key = DataEncryption.get_encryption_key()
f = Fernet(key)
decoded = base64.urlsafe_b64decode(encrypted_data.encode())
decrypted = f.decrypt(decoded)
return decrypted.decode()
except Exception:
return encrypted_data # Return original if decryption fails
class InputSanitizer:
"""
Sanitize user input to prevent XSS and injection attacks.
"""
@staticmethod
def sanitize_html(text):
"""Remove potentially dangerous HTML."""
if not text:
return text
import html
# Escape HTML entities
text = html.escape(text)
return text
@staticmethod
def sanitize_sql(text):
"""Basic SQL injection prevention (Django ORM handles this, but extra check)."""
if not text:
return text
# Remove SQL keywords
dangerous = ['DROP', 'DELETE', 'INSERT', 'UPDATE', 'SELECT', 'UNION', '--', ';']
text_upper = text.upper()
for keyword in dangerous:
if keyword in text_upper:
# Log potential SQL injection attempt
return None
return text
@staticmethod
def validate_email(email):
"""Validate email format."""
import re
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return bool(re.match(pattern, email))
@staticmethod
def validate_url(url):
"""Validate URL format."""
import re
pattern = r'^https?://[^\s/$.?#].[^\s]*$'
return bool(re.match(pattern, url))
class PasswordSecurity:
"""
Enhanced password security utilities.
"""
@staticmethod
def check_password_strength(password):
"""Check password strength."""
if len(password) < 12:
return False, "Password must be at least 12 characters long"
if not any(c.isupper() for c in password):
return False, "Password must contain at least one uppercase letter"
if not any(c.islower() for c in password):
return False, "Password must contain at least one lowercase letter"
if not any(c.isdigit() for c in password):
return False, "Password must contain at least one number"
if not any(c in "!@#$%^&*()_+-=[]{}|;:,.<>?" for c in password):
return False, "Password must contain at least one special character"
# Check for common patterns
common_patterns = ['123456', 'password', 'qwerty', 'abc123']
password_lower = password.lower()
for pattern in common_patterns:
if pattern in password_lower:
return False, "Password contains common patterns"
return True, "Password is strong"
@staticmethod
def hash_sensitive_data(data):
"""Hash sensitive data for storage."""
return hashlib.sha256(data.encode()).hexdigest()