"""토큰 암호화 — Fernet(AES-128-CBC + HMAC). DB 덤프가 유출돼도 access/refresh token 이 평문으로 남지 않게 한다. 키는 .env 의 CAFE24_TOKEN_SECRET 하나이며, 임의 길이 문자열을 받아 SHA-256 으로 32바이트를 만든 뒤 Fernet 키 형식으로 변환한다 (운영자가 `openssl rand -hex 32` 같은 익숙한 방식을 그대로 쓰게 하려는 것). ⚠️ CAFE24_TOKEN_SECRET 을 바꾸면 기존 저장 토큰은 복호화할 수 없다. 그 경우 관리자 화면에서 카페24 재연결(재인증)을 하면 된다. """ from __future__ import annotations import base64 import hashlib from .errors import Cafe24ConfigError def _fernet(secret: str): from cryptography.fernet import Fernet # 지연 import if not (secret or "").strip(): raise Cafe24ConfigError( "CAFE24_TOKEN_SECRET 환경변수가 설정되지 않았습니다. " "openssl rand -hex 32 로 값을 만들어 .env 에 넣고 컨테이너를 재기동하세요." ) digest = hashlib.sha256(secret.strip().encode("utf-8")).digest() return Fernet(base64.urlsafe_b64encode(digest)) def encrypt(value: str, *, secret: str) -> str: """평문 → 암호문. 빈 문자열은 그대로 둔다(미연결 상태 표현).""" if not value: return "" return _fernet(secret).encrypt(value.encode("utf-8")).decode("ascii") def decrypt(value: str, *, secret: str) -> str: """암호문 → 평문. 키가 바뀌었거나 손상되면 Cafe24ConfigError.""" if not value: return "" from cryptography.fernet import InvalidToken # 지연 import try: return _fernet(secret).decrypt(value.encode("ascii")).decode("utf-8") except InvalidToken: raise Cafe24ConfigError( "저장된 카페24 토큰을 복호화하지 못했습니다. " "CAFE24_TOKEN_SECRET 이 변경되었을 수 있습니다. 카페24 재연결이 필요합니다." ) from None