41 lines
1.3 KiB
Python
41 lines
1.3 KiB
Python
from cryptography.fernet import Fernet, InvalidToken
|
|
from django.conf import settings
|
|
|
|
|
|
class CredentialEncryptionError(ValueError):
|
|
pass
|
|
|
|
|
|
def _fernet() -> Fernet:
|
|
key = settings.AI_CREDENTIAL_ENCRYPTION_KEY
|
|
if not key:
|
|
raise CredentialEncryptionError("AI credential encryption key is not configured")
|
|
try:
|
|
return Fernet(key.encode("utf-8"))
|
|
except (TypeError, ValueError) as error:
|
|
raise CredentialEncryptionError("AI credential encryption key is invalid") from error
|
|
|
|
|
|
def encrypt_secret(value: str) -> str:
|
|
if not value:
|
|
raise CredentialEncryptionError("API key is required")
|
|
return _fernet().encrypt(value.encode("utf-8")).decode("utf-8")
|
|
|
|
|
|
def decrypt_secret(value: str) -> str:
|
|
if not value:
|
|
raise CredentialEncryptionError("API key is not configured")
|
|
try:
|
|
return _fernet().decrypt(value.encode("utf-8")).decode("utf-8")
|
|
except InvalidToken as error:
|
|
raise CredentialEncryptionError("Stored API key cannot be decrypted") from error
|
|
|
|
|
|
def mask_secret(value: str) -> str:
|
|
try:
|
|
plain = decrypt_secret(value)
|
|
except CredentialEncryptionError:
|
|
return "已配置" if value else "未配置"
|
|
suffix = plain[-4:] if len(plain) >= 4 else plain
|
|
return f"****{suffix}"
|