- 日志时间改为北京时间(TZ=Asia/Shanghai) - 评论达上限后继续执行点赞/收藏/转发 - 用户信息同步改用 PATCH /v2/users/current - 一键登出全部功能 - 一键登出全部前端按钮 - update.sh 一键更新脚本
50 lines
1.4 KiB
Python
Executable File
50 lines
1.4 KiB
Python
Executable File
"""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]
|