44 lines
1.0 KiB
Python
44 lines
1.0 KiB
Python
import base64
|
|
import hashlib
|
|
import os
|
|
|
|
from cryptography.fernet import Fernet, InvalidToken
|
|
|
|
_PREFIX = "enc$"
|
|
|
|
|
|
def _master_secret() -> str:
|
|
return (
|
|
os.environ.get("NOVELA_MASTER_KEY")
|
|
or os.environ.get("POSTGRES_PASSWORD")
|
|
or "novela-default-key-change-me"
|
|
)
|
|
|
|
|
|
def _fernet() -> Fernet:
|
|
digest = hashlib.sha256(_master_secret().encode("utf-8")).digest()
|
|
key = base64.urlsafe_b64encode(digest)
|
|
return Fernet(key)
|
|
|
|
|
|
def encrypt_value(value: str | None) -> str:
|
|
raw = value or ""
|
|
token = _fernet().encrypt(raw.encode("utf-8")).decode("utf-8")
|
|
return _PREFIX + token
|
|
|
|
|
|
def is_encrypted_value(value: str | None) -> bool:
|
|
return bool(value) and str(value).startswith(_PREFIX)
|
|
|
|
|
|
def decrypt_value(value: str | None) -> str:
|
|
if not value:
|
|
return ""
|
|
if not value.startswith(_PREFIX):
|
|
return value
|
|
token = value[len(_PREFIX) :]
|
|
try:
|
|
return _fernet().decrypt(token.encode("utf-8")).decode("utf-8")
|
|
except InvalidToken:
|
|
return ""
|