@@ -0,0 +1,45 @@
|
||||
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
|
||||
Reference in New Issue
Block a user