""" HTML 模板加密/解密模块 使用 AES (Fernet) 对 HTML 资源进行加密存储,运行时解密后渲染 """ import base64 import os from cryptography.fernet import Fernet from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC def _get_fernet_key() -> bytes: """从环境变量 HTML_ENCRYPT_KEY 派生 Fernet 密钥,若未设置则使用默认开发密钥""" raw = os.environ.get( "HTML_ENCRYPT_KEY", "maixiang_html_encrypt_default_key_change_in_production", ) # 使用 PBKDF2 派生 32 字节密钥,再转为 Fernet 所需的 base64url kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), length=32, salt=b"maixiang_html_salt", iterations=100000, ) key_bytes = kdf.derive(raw.encode("utf-8")) return base64.urlsafe_b64encode(key_bytes) def encrypt(plain_data: bytes) -> bytes: """加密原始数据,返回密文(bytes)""" key = _get_fernet_key() f = Fernet(key) return f.encrypt(plain_data) def decrypt(encrypted_data: bytes) -> bytes: """解密数据,返回明文(bytes)""" key = _get_fernet_key() f = Fernet(key) return f.decrypt(encrypted_data) def encrypt_file(path: str) -> None: """就地加密文件:读取 UTF-8 内容,加密后写回同一路径""" with open(path, "rb") as f: plain = f.read() encrypted = encrypt(plain) with open(path, "wb") as f: f.write(encrypted) def decrypt_file(path: str) -> None: """就地解密文件:读取密文,解密后以 UTF-8 写回同一路径""" with open(path, "rb") as f: encrypted = f.read() plain = decrypt(encrypted) with open(path, "wb") as f: f.write(plain) def is_encrypted(data: bytes) -> bool: """简单启发式:Fernet 密文以 b'gAAAAA' 开头(base64 编码后)""" try: return data[:7] == b"gAAAAAB" except Exception: return False