Spaces:
Sleeping
Sleeping
| """Token encryption at rest for GitHub/HF OAuth tokens. | |
| Uses Fernet (AES-128-CBC with HMAC-SHA256) from the ``cryptography`` package. | |
| The encryption key is loaded from the ``ENCRYPTION_KEY`` environment variable | |
| (a Fernet key, 32 url-safe base64 bytes). If the env var is absent, a | |
| per-process ephemeral key is generated (data is lost on restart — fine for | |
| ephemeral Space containers, but NOT suitable for durable storage). | |
| """ | |
| from __future__ import annotations | |
| import os | |
| import secrets | |
| _fernet = None | |
| def _get_fernet(): | |
| """Lazy-init Fernet cipher from ENCRYPTION_KEY env var.""" | |
| global _fernet | |
| if _fernet is not None: | |
| return _fernet | |
| from cryptography.fernet import Fernet | |
| key = os.environ.get("ENCRYPTION_KEY", "").strip() | |
| if not key: | |
| # ephemeral key — fine for single-restart HF Space containers | |
| key = Fernet.generate_key().decode() | |
| os.environ["ENCRYPTION_KEY"] = key | |
| _fernet = Fernet(key.encode() if isinstance(key, str) else key) | |
| return _fernet | |
| def encrypt_token(plaintext: str) -> str: | |
| """Encrypt a token string for storage. Returns a URL-safe base64 string.""" | |
| f = _get_fernet() | |
| return f.encrypt(plaintext.encode("utf-8")).decode("ascii") | |
| def decrypt_token(ciphertext: str) -> str: | |
| """Decrypt a stored token. Returns the original plaintext string.""" | |
| f = _get_fernet() | |
| return f.decrypt(ciphertext.encode("ascii")).decode("utf-8") | |
| def mask_token(token: str) -> str: | |
| """Return a masked version of a token for safe logging: ``ghp_****abcd``.""" | |
| if len(token) <= 8: | |
| return "****" | |
| return token[:4] + "****" + token[-4:] | |