Files

51 lines
1.4 KiB
Python

# 数据库字段加密(AES-256-GCM)。与 app.core.crypto 的接口报文加密相互独立。
import base64
import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from fastapi import HTTPException, status
from app.core.config import get_settings
_DETAIL = "字段加密未配置"
def _fail() -> None:
raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail=_DETAIL)
def _key() -> bytes:
raw = "".join(get_settings().field_aes_key.split())
if not raw:
_fail()
try:
key = base64.b64decode(raw, validate=True)
except Exception:
_fail()
if len(key) != 32:
_fail()
return key
def encrypt_text(plain: str) -> str:
if plain == "":
return ""
nonce = os.urandom(12)
ciphertext = AESGCM(_key()).encrypt(nonce, plain.encode("utf-8"), None)
return base64.b64encode(nonce + ciphertext).decode("ascii")
def decrypt_text(token: str) -> str:
if token == "":
return ""
try:
raw = base64.b64decode(token, validate=True)
if len(raw) < 13:
raise ValueError("short")
plain = AESGCM(_key()).decrypt(raw[:12], raw[12:], None)
return plain.decode("utf-8")
except HTTPException:
raise
except Exception:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="字段密文无法解密") from None