# 보안 가이드 (SECURITY.md)

## 🔐 보안 철학

Todo-Project는 **개인용 도구**로 설계되어 **편의성**과 **적절한 보안** 사이의 균형을 추구합니다.

### 보안 원칙
- **Trust but Verify**: 신뢰할 수 있는 기기에서는 간편하게, 의심스러운 접근은 차단
- **최소 권한**: 필요한 최소한의 권한만 부여
- **개인 최적화**: 개인 사용에 최적화된 보안 모델

## 🛡️ 보안 레벨

### 1. Minimal (개인용 권장)
```python
SECURITY_MINIMAL = {
    "device_remember_days": 30,      # 30일간 기기 기억
    "require_password": False,       # 기기 등록 후 비밀번호 불필요
    "session_timeout": 0,            # 무제한 세션
    "biometric_optional": True,      # 생체 인증 선택사항
    "auto_login": True               # 자동 로그인 활성화
}
```

**적합한 환경**: 개인 기기 (내 폰, 내 컴퓨터)에서만 사용

### 2. Balanced (일반 권장)
```python
SECURITY_BALANCED = {
    "device_remember_days": 7,       # 7일간 기기 기억
    "require_password": True,        # 주기적 비밀번호 확인
    "session_timeout": 24*60,        # 24시간 세션
    "biometric_optional": True,      # 생체 인증 선택사항
    "auto_login": False              # 수동 로그인
}
```

**적합한 환경**: 가끔 다른 기기에서도 접근하는 경우

### 3. Secure (높은 보안)
```python
SECURITY_SECURE = {
    "device_remember_days": 1,       # 1일간만 기기 기억
    "require_password": True,        # 매번 비밀번호 확인
    "session_timeout": 60,           # 1시간 세션
    "biometric_required": True,      # 생체 인증 필수
    "auto_login": False              # 수동 로그인
}
```

**적합한 환경**: 민감한 정보가 포함된 경우

## 🔑 인증 시스템

### 기기 등록 방식

#### 기기 식별
```python
class DeviceFingerprint:
    """기기 고유 식별자 생성"""
    
    def generate_fingerprint(self, request):
        """브라우저 fingerprint 생성"""
        components = [
            request.headers.get('User-Agent', ''),
            request.headers.get('Accept-Language', ''),
            request.headers.get('Accept-Encoding', ''),
            self.get_screen_resolution(),  # JavaScript에서 전송
            self.get_timezone(),           # JavaScript에서 전송
            self.get_platform_info()       # JavaScript에서 전송
        ]
        
        fingerprint = hashlib.sha256(
            '|'.join(components).encode('utf-8')
        ).hexdigest()
        
        return fingerprint[:16]  # 16자리 축약
```

#### 기기 등록 프로세스
```python
class DeviceRegistration:
    """기기 등록 관리"""
    
    async def register_device(self, user_id, device_info, user_confirmation):
        """새 기기 등록"""
        
        # 1. 사용자 확인 (비밀번호 또는 기존 기기에서 승인)
        if not await self.verify_user_identity(user_id, user_confirmation):
            raise AuthenticationError("사용자 확인 실패")
        
        # 2. 기기 정보 생성
        device_id = self.generate_device_id(device_info)
        device_name = device_info.get('name', '알 수 없는 기기')
        
        # 3. 장기 토큰 생성 (30일 유효)
        device_token = self.create_device_token(user_id, device_id)
        
        # 4. 기기 정보 저장
        device_record = {
            "device_id": device_id,
            "user_id": user_id,
            "device_name": device_name,
            "fingerprint": device_info['fingerprint'],
            "registered_at": datetime.now(),
            "last_used": datetime.now(),
            "token": device_token,
            "expires_at": datetime.now() + timedelta(days=30),
            "is_trusted": True
        }
        
        await self.save_device_record(device_record)
        return device_token
```

### 토큰 관리

#### JWT 토큰 구조
```python
class TokenManager:
    """토큰 생성 및 관리"""
    
    def create_device_token(self, user_id, device_id):
        """장기간 유효한 기기 토큰 생성"""
        payload = {
            "user_id": str(user_id),
            "device_id": device_id,
            "token_type": "device",
            "issued_at": datetime.utcnow(),
            "expires_at": datetime.utcnow() + timedelta(days=30)
        }
        
        return jwt.encode(payload, settings.SECRET_KEY, algorithm="HS256")
    
    def create_session_token(self, user_id, device_id):
        """세션 토큰 생성"""
        payload = {
            "user_id": str(user_id),
            "device_id": device_id,
            "token_type": "session",
            "issued_at": datetime.utcnow(),
            "expires_at": datetime.utcnow() + timedelta(hours=24)
        }
        
        return jwt.encode(payload, settings.SECRET_KEY, algorithm="HS256")
```

#### 토큰 검증
```python
class TokenValidator:
    """토큰 검증"""
    
    async def validate_device_token(self, token):
        """기기 토큰 검증"""
        try:
            payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
            
            # 토큰 타입 확인
            if payload.get("token_type") != "device":
                return None
            
            # 만료 시간 확인
            expires_at = datetime.fromisoformat(payload["expires_at"])
            if datetime.utcnow() > expires_at:
                return None
            
            # 기기 정보 확인
            device_record = await self.get_device_record(
                payload["user_id"], 
                payload["device_id"]
            )
            
            if not device_record or not device_record["is_trusted"]:
                return None
            
            return payload
            
        except jwt.JWTError:
            return None
```

## 🔒 데이터 보안

### 데이터베이스 보안

#### 비밀번호 해싱
```python
from passlib.context import CryptContext

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def hash_password(password: str) -> str:
    """비밀번호 해싱 (bcrypt)"""
    return pwd_context.hash(password)

def verify_password(plain_password: str, hashed_password: str) -> bool:
    """비밀번호 검증"""
    return pwd_context.verify(plain_password, hashed_password)
```

#### 민감 정보 암호화
```python
from cryptography.fernet import Fernet

class DataEncryption:
    """민감 정보 암호화"""
    
    def __init__(self):
        self.key = settings.ENCRYPTION_KEY.encode()
        self.cipher = Fernet(self.key)
    
    def encrypt_sensitive_data(self, data: str) -> str:
        """민감 정보 암호화 (시놀로지 비밀번호 등)"""
        return self.cipher.encrypt(data.encode()).decode()
    
    def decrypt_sensitive_data(self, encrypted_data: str) -> str:
        """민감 정보 복호화"""
        return self.cipher.decrypt(encrypted_data.encode()).decode()
```

### 네트워크 보안

#### HTTPS 강제
```python
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware

# 프로덕션에서 HTTPS 강제
if not settings.DEBUG:
    app.add_middleware(HTTPSRedirectMiddleware)
```

#### CORS 설정
```python
from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.ALLOWED_ORIGINS,  # 특정 도메인만 허용
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["*"],
)
```

## 🚨 보안 모니터링

### 로그인 시도 모니터링
```python
class SecurityMonitor:
    """보안 모니터링"""
    
    def __init__(self):
        self.failed_attempts = {}  # IP별 실패 횟수
        self.blocked_ips = set()   # 차단된 IP
    
    async def record_login_attempt(self, ip_address, success):
        """로그인 시도 기록"""
        if success:
            # 성공 시 실패 횟수 초기화
            self.failed_attempts.pop(ip_address, None)
        else:
            # 실패 시 횟수 증가
            self.failed_attempts[ip_address] = \
                self.failed_attempts.get(ip_address, 0) + 1
            
            # 5회 실패 시 30분 차단
            if self.failed_attempts[ip_address] >= 5:
                self.block_ip(ip_address, minutes=30)
    
    def block_ip(self, ip_address, minutes=30):
        """IP 주소 차단"""
        self.blocked_ips.add(ip_address)
        
        # 일정 시간 후 차단 해제
        asyncio.create_task(
            self.unblock_ip_after(ip_address, minutes)
        )
```

### 의심스러운 활동 감지
```python
class AnomalyDetection:
    """이상 활동 감지"""
    
    async def detect_suspicious_activity(self, user_id, activity):
        """의심스러운 활동 감지"""
        
        # 1. 비정상적인 시간대 접근
        if self.is_unusual_time(activity.timestamp):
            await self.alert_unusual_time_access(user_id, activity)
        
        # 2. 새로운 기기에서 접근
        if not await self.is_known_device(user_id, activity.device_info):
            await self.alert_new_device_access(user_id, activity)
        
        # 3. 비정상적인 API 호출 패턴
        if await self.is_unusual_api_pattern(user_id, activity):
            await self.alert_unusual_api_pattern(user_id, activity)
```

## 🔧 보안 설정

### 환경 변수 보안
```bash
# .env 파일 보안 설정
SECRET_KEY=your-very-long-and-random-secret-key-here
ENCRYPTION_KEY=your-32-byte-encryption-key-here

# 시놀로지 인증 정보 (암호화 저장)
SYNOLOGY_USERNAME=encrypted_username
SYNOLOGY_PASSWORD=encrypted_password

# 보안 레벨 설정
SECURITY_LEVEL=minimal  # minimal, balanced, secure
ENABLE_DEVICE_REGISTRATION=true
ENABLE_BIOMETRIC_AUTH=true
ENABLE_SECURITY_MONITORING=true

# 세션 설정
SESSION_TIMEOUT_MINUTES=1440  # 24시간
DEVICE_REMEMBER_DAYS=30
```

### 보안 헤더
```python
from fastapi.middleware.trustedhost import TrustedHostMiddleware
from fastapi.responses import Response

# 신뢰할 수 있는 호스트만 허용
app.add_middleware(
    TrustedHostMiddleware, 
    allowed_hosts=["localhost", "127.0.0.1", "your-domain.com"]
)

@app.middleware("http")
async def add_security_headers(request, call_next):
    """보안 헤더 추가"""
    response = await call_next(request)
    
    response.headers["X-Content-Type-Options"] = "nosniff"
    response.headers["X-Frame-Options"] = "DENY"
    response.headers["X-XSS-Protection"] = "1; mode=block"
    response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
    
    return response
```

## 🛠️ 보안 체크리스트

### 개발 환경
- [ ] `.env` 파일이 `.gitignore`에 포함되어 있는가?
- [ ] 기본 비밀번호가 변경되었는가?
- [ ] 디버그 모드가 비활성화되어 있는가? (프로덕션)
- [ ] 로그에 민감 정보가 포함되지 않는가?

### 인증 시스템
- [ ] 비밀번호가 안전하게 해싱되어 있는가?
- [ ] JWT 토큰에 민감 정보가 포함되지 않는가?
- [ ] 토큰 만료 시간이 적절하게 설정되어 있는가?
- [ ] 기기 등록 프로세스가 안전한가?

### 네트워크 보안
- [ ] HTTPS가 활성화되어 있는가? (프로덕션)
- [ ] CORS 설정이 적절한가?
- [ ] 보안 헤더가 설정되어 있는가?
- [ ] 불필요한 포트가 차단되어 있는가?

### 데이터 보안
- [ ] 민감 정보가 암호화되어 있는가?
- [ ] 데이터베이스 접근이 제한되어 있는가?
- [ ] 백업 데이터가 안전하게 보관되어 있는가?
- [ ] 로그 파일이 안전하게 관리되어 있는가?

## 🚨 보안 사고 대응

### 사고 대응 절차
1. **즉시 조치**: 의심스러운 접근 차단
2. **영향 평가**: 피해 범위 확인
3. **복구 작업**: 시스템 정상화
4. **사후 분석**: 원인 분석 및 재발 방지

### 비상 연락처
- **시스템 관리자**: [연락처]
- **보안 담당자**: [연락처]
- **시놀로지 지원**: [연락처]

이 보안 가이드를 통해 안전하고 편리한 Todo 시스템을 구축할 수 있습니다.
