# backend/app/auth/tokens.py — 세션 id 서명/검증 + API 토큰 해시 (stdlib hmac, 의존성 없음) import base64 import hashlib import hmac import secrets from ..config import get_settings def _key() -> bytes: return get_settings().session_secret.encode("utf-8") def new_session_id() -> str: return secrets.token_hex(32) # 256-bit def new_api_token() -> str: return "ari_" + secrets.token_urlsafe(32) def hash_token(token: str) -> str: return hashlib.sha256(token.encode("utf-8")).hexdigest() def sign_session_id(sid: str) -> str: """sid. — 쿠키에 들어가는 서명된 세션 id.""" mac = hmac.new(_key(), sid.encode("utf-8"), hashlib.sha256).digest() return f"{sid}.{base64.urlsafe_b64encode(mac).decode().rstrip('=')}" def unsign_session_id(signed: str) -> str | None: """서명 검증 후 sid 반환. 변조/형식 오류면 None.""" try: sid, sig = signed.rsplit(".", 1) except ValueError: return None expected = ( base64.urlsafe_b64encode(hmac.new(_key(), sid.encode("utf-8"), hashlib.sha256).digest()) .decode() .rstrip("=") ) return sid if hmac.compare_digest(sig, expected) else None