update
This commit is contained in:
134
accounts/security.py
Normal file
134
accounts/security.py
Normal 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()
|
||||
|
||||
Reference in New Issue
Block a user