76f5d30db1
Co-authored-by: GitHub Copilot <noreply@github.com>
46 lines
1.4 KiB
Python
46 lines
1.4 KiB
Python
import base64
|
|
import hashlib
|
|
import os
|
|
|
|
from cryptography.fernet import Fernet, InvalidToken
|
|
|
|
_ENCRYPTED_PREFIX = "enc:v1:"
|
|
|
|
|
|
def get_session_secret() -> str:
|
|
secret = os.environ.get("RADIOSYNC_SECRET_KEY")
|
|
if not secret:
|
|
raise RuntimeError("RADIOSYNC_SECRET_KEY must be set")
|
|
return secret
|
|
|
|
|
|
def _get_fernet() -> Fernet:
|
|
configured_key = os.environ.get("RADIOSYNC_CONFIG_KEY")
|
|
if configured_key:
|
|
try:
|
|
return Fernet(configured_key.encode("ascii"))
|
|
except Exception as exc:
|
|
raise RuntimeError("RADIOSYNC_CONFIG_KEY must be a valid Fernet key") from exc
|
|
|
|
digest = hashlib.sha256(get_session_secret().encode("utf-8")).digest()
|
|
return Fernet(base64.urlsafe_b64encode(digest))
|
|
|
|
|
|
def encrypt_config_value(value: str) -> str:
|
|
if value is None:
|
|
return None
|
|
if value.startswith(_ENCRYPTED_PREFIX):
|
|
return value
|
|
token = _get_fernet().encrypt(value.encode("utf-8")).decode("ascii")
|
|
return f"{_ENCRYPTED_PREFIX}{token}"
|
|
|
|
|
|
def decrypt_config_value(value: str) -> str:
|
|
if value is None or not value.startswith(_ENCRYPTED_PREFIX):
|
|
return value
|
|
try:
|
|
token = value[len(_ENCRYPTED_PREFIX):].encode("ascii")
|
|
return _get_fernet().decrypt(token).decode("utf-8")
|
|
except InvalidToken as exc:
|
|
raise RuntimeError("Cannot decrypt config value with the configured key") from exc
|