"""AES加密工具 - 用于密码和API Key加密存储""" import base64 import hashlib from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad from app.core.config import settings def _get_key() -> bytes: """获取32字节AES密钥""" key = settings.AES_KEY.encode("utf-8") return hashlib.sha256(key).digest() def encrypt(plaintext: str) -> str: """AES-CBC加密""" if not plaintext: return "" key = _get_key() cipher = AES.new(key, AES.MODE_CBC) ct_bytes = cipher.encrypt(pad(plaintext.encode("utf-8"), AES.block_size)) iv = base64.b64encode(cipher.iv).decode("utf-8") ct = base64.b64encode(ct_bytes).decode("utf-8") return f"{iv}:{ct}" def decrypt(ciphertext: str) -> str: """AES-CBC解密""" if not ciphertext or ":" not in ciphertext: return "" try: iv_str, ct_str = ciphertext.split(":", 1) key = _get_key() iv = base64.b64decode(iv_str) ct = base64.b64decode(ct_str) cipher = AES.new(key, AES.MODE_CBC, iv) pt = unpad(cipher.decrypt(ct), AES.block_size) return pt.decode("utf-8") except Exception: return "" def mask_password(password: str) -> str: """密码脱敏显示""" if not password: return "" if len(password) <= 2: return "*" * len(password) return password[0] + "*" * (len(password) - 2) + password[-1]