mirror of
https://github.com/ThearchyHelios/AgentLab.git
synced 2026-11-15 23:11:58 +00:00
dead51ae56
- 工件(内容寻址):以前共用 <id>.tmp,两个进程同时写同一份内容时后到的会截断先到的半成品、先到的改名又让后到的改名失败;现在各写各的临时文件 - 加密密钥 .secret_key、断言签名私钥:几个进程同时第一次启动时只建出一把,后到的读先到的那一把(以前各生成一把,各自加密、签名的东西对方认不得),文件从建出来起就是 0600 - 附件抽出文字的缓存:临时文件名带随机后缀 - 文件工具(file_write)的覆盖和追加、三种系统沙箱写进工作目录的代码和输入文件、seatbelt 的策略文件:先写临时文件再改名 - 上传表格的版本库、原件存档、记录表本来就是这样写的,不动
61 lines
1.9 KiB
Python
61 lines
1.9 KiB
Python
from __future__ import annotations
|
|
|
|
import base64
|
|
import hashlib
|
|
import os
|
|
|
|
from cryptography.fernet import Fernet, InvalidToken
|
|
|
|
from app.core import atomic
|
|
from app.core.config import settings
|
|
|
|
_PREFIX = "enc::"
|
|
|
|
|
|
def _load_key() -> bytes:
|
|
"""取加密密钥:优先用配置里的 secret_key,否则在 data_dir 生成一个持久化的。"""
|
|
raw = settings.secret_key
|
|
if not raw:
|
|
key_file = settings.data_dir / ".secret_key"
|
|
if not key_file.exists():
|
|
# 只建一次(core/atomic.create_text):两个进程同时第一次启动,后到的读先到的那一把,不会各拿一把、
|
|
# 各自加密的东西对方解不开
|
|
atomic.create_text(key_file, base64.urlsafe_b64encode(os.urandom(32)).decode(), mode=0o600)
|
|
raw = key_file.read_text().strip()
|
|
# 任意字符串都归一化成 32 字节 Fernet key
|
|
digest = hashlib.sha256(raw.encode()).digest()
|
|
return base64.urlsafe_b64encode(digest)
|
|
|
|
|
|
_fernet = Fernet(_load_key())
|
|
|
|
|
|
def encrypt(value: str | None) -> str | None:
|
|
"""加密明文。已经是密文的原样返回,方便重复保存同一条记录。"""
|
|
if not value:
|
|
return value
|
|
if value.startswith(_PREFIX):
|
|
return value
|
|
return _PREFIX + _fernet.encrypt(value.encode()).decode()
|
|
|
|
|
|
def decrypt(value: str | None) -> str | None:
|
|
if not value:
|
|
return value
|
|
if not value.startswith(_PREFIX):
|
|
return value # 兼容历史明文
|
|
try:
|
|
return _fernet.decrypt(value[len(_PREFIX) :].encode()).decode()
|
|
except InvalidToken:
|
|
return None
|
|
|
|
|
|
def mask(value: str | None) -> str:
|
|
"""给前端展示用的掩码,永远不把明文 key 发回浏览器。"""
|
|
if not value:
|
|
return ""
|
|
plain = decrypt(value) or ""
|
|
if len(plain) <= 8:
|
|
return "••••"
|
|
return f"{plain[:4]}••••{plain[-4:]}"
|