41 lines
1.3 KiB
Python
41 lines
1.3 KiB
Python
"""凭证加密模块(Fernet 对称加密)
|
||
|
||
用于加密存储 SSH 密钥、密码、API Key、平台 API 配置等敏感信息。
|
||
MASTER_KEY 从 .env 读取,不入库。
|
||
"""
|
||
|
||
from typing import Optional
|
||
|
||
from cryptography.fernet import Fernet, InvalidToken
|
||
|
||
from app.core.config import settings
|
||
|
||
|
||
def _get_fernet() -> Fernet:
|
||
"""获取 Fernet 实例(MASTER_KEY 未配置时抛错)"""
|
||
key = settings.MASTER_KEY
|
||
if not key:
|
||
raise RuntimeError(
|
||
"MASTER_KEY 未配置,无法加解密凭证。请在 .env 设置 MASTER_KEY,"
|
||
"生成命令:python -c 'from cryptography.fernet import Fernet; "
|
||
"print(Fernet.generate_key().decode())'"
|
||
)
|
||
return Fernet(key.encode() if isinstance(key, str) else key)
|
||
|
||
|
||
def encrypt(plain: Optional[str]) -> Optional[str]:
|
||
"""加密明文,返回 token 字符串;空值原样返回 None"""
|
||
if plain is None or plain == "":
|
||
return None
|
||
return _get_fernet().encrypt(plain.encode()).decode()
|
||
|
||
|
||
def decrypt(token: Optional[str]) -> Optional[str]:
|
||
"""解密 token,返回明文;空值或解密失败返回 None"""
|
||
if not token:
|
||
return None
|
||
try:
|
||
return _get_fernet().decrypt(token.encode()).decode()
|
||
except (InvalidToken, ValueError):
|
||
return None
|