加密备份恢复实验——仅使用人工测试材料 实测日期:2026-09-03 测试内容 -------- 实验环境为 restic 0.19.1、Python 3.12.10 和 Windows 11 amd64。 12个生成的文件覆盖 UTF-8 文本、JSON、CSV、XML、ZIP、WAV 和 TOML。 其中没有个人文档、照片、真实录音或真实凭据。 这是一种本地测试设计,不是备份产品比较,也不是通用安全评级。 开发阶段的运行与最终记录的运行得到了相同的6行结果;它们不是 在不同机器上完成的独立测试。 仓库格式为2。压缩使用 restic 默认值 auto,禁用缓存。 每次备份成功后,脚本取得完整快照 ID。恢复时使用该固定 ID, 并选取人工 /source 子文件夹,从不使用特殊标识 latest。 每个恢复位置都位于新建的实验根目录下,是新建的空文件夹, 同时设置 --overwrite never,禁止覆盖已有文件。 S4 的12文件预期清单在应用排除规则之前建立。 S5 的“所需当前版本”清单在保存旧版测试文件之前建立。 S6 的清单在备份前记录故意生成的无效源文件,也记录源文件未通过 JSON 解析测试。不会把不完整的快照或快照自身的文件列表, 当作“原本应该保存什么”的参考依据。 各项检查回答不同的问题: * restic check:仓库能否通过普通结构检查? * restic check --read-data:读取全部存储数据后,能否通过检查? * restic restore:取出文件的操作是否以退出代码0结束? * 文件清单:预期路径是否全部存在,且没有多余文件? * SHA256:全部预期恢复文件是否符合事先建立的预期清单? * 格式解析:指定的标准读取程序能否读取恢复文件? 实测结果 -------- 案例 check read-data restore 路径 SHA256 格式解析(实际存在文件) S1 0 0 0 12/12 12/12 12/12 S2 12 12 12 0/12 0/12 未执行(0个文件) S3 0 1 1 11/12 11/12 11/11 S4 0 0 0 11/12 11/12 11/11 S5 0 0 0 12/12 11/12 12/12 S6 0 0 0 12/12 12/12 11/12 退出代码0表示操作成功完成。本次运行中,12表示公开的虚拟测试密码 错误;1表示数据、读取或恢复错误。JSON 结果与命令日志保留了 各项操作和诊断信息。不能把退出代码0解释为“用户的全部恢复目标 已经实现”。 S1:人工源文件未作改动。全部预期路径、字节比对和格式解析均通过。 S2:对 S1 仓库的副本使用一个故意设置错误的公开测试密码,未恢复出 文件。这只检验了程序是否拒绝这个错误密码,没有检验是否存在其他 可用的恢复密钥。 S3:在 S1 仓库的一次性副本中,翻转一个数据块内的一个密文字节。 脚本根据已知内容哈希,在 restic 索引中定位 documents/records.json 对应的单一数据块,再修改其16字节 nonce(加密操作使用的随机值)之后的那个字节。 数据包大小与头部均未改变。普通检查通过,全量读取和恢复失败, 最终恢复出11个文件。确切的数据包及数据块 ID、字节偏移量、 数据包校验值与缺失文件,均见 results.json。 这一结果只针对这项损坏测试;普通检查能发现其他类型的损坏。 S4:先记录完整预期清单,再从备份中排除 documents/contacts.csv。 restic 的所有操作都通过,但独立文件清单和全部文件哈希比对 仅有11/12符合要求,因此未通过完整性核对。 S5:已有较新快照,却恢复了完整的旧快照。 documents/status.json 是修订版1,所需的却是修订版2。 12个文件均可解析,但只有11个符合所需当前版本清单。 与另行保留的旧源文件清单比对时,12个文件全部相符。 这是正确恢复了不符合目标的版本,并非 restic 造成损坏。 S6:documents/records.json 在备份前已是无效 JSON。 synthetic-manifests.json 记录了源文件的解析失败。 恢复后的全部字节与源文件相符,但同一个 JSON 解析程序依然 无法读取该文件。无效内容不是恢复过程造成的。 格式解析列的含义 ---------------- 只尝试读取实际存在的文件。缺失文件由文件清单列报告,不能算作 格式解析成功。TXT 使用严格的 UTF-8 解码;JSON 使用 json.loads; CSV 使用严格模式的 csv.reader,并检查每行列数是否一致; XML 使用 ElementTree.parse;ZIP 读取所有内部文件并检查 CRC 校验值;WAV 读取全部声明的音频帧并检查字节长度; TOML 使用 tomllib.loads。 这些是真实的读取与解析操作,不是检查文件扩展名。 通过解析不代表某个桌面应用能完整显示全部功能,也不代表内容 符合个人的实际需求。 公开附件 -------- restore-lab.py 最终复现脚本,仅使用 Python 标准库。 results.csv 简明数值结果。 results.json 各文件结果、快照 ID、程序来源、脚本哈希, 以及损坏测试细节。 synthetic-manifests.json 事先建立的预期基准与源文件解析结果。 command-log.json 实际命令、退出代码、标准输出和错误输出。 实验路径、执行账号名称和时间戳字段已脱敏; 操作结果没有删改。 lab-readme.txt 本方法说明与结果解释。 在 Windows amd64 上复现 ----------------------- 需要 Python 3.11 或更高版本,以及下列官方 ZIP。 本次记录使用 Python 3.12.10。将 restore-lab.py 放入新建的工作 文件夹。下载官方版本 ZIP,并将其 SHA256 与官方 SHA256SUMS 文件比对。脚本会强制检查下列 ZIP 和可执行文件哈希。 脚本本身不会下载任何内容,也不要求将 restic 安装到系统环境中。 发布页: https://github.com/restic/restic/releases/tag/v0.19.1 ZIP: https://github.com/restic/restic/releases/download/v0.19.1/restic_0.19.1_windows_amd64.zip 官方校验值: https://github.com/restic/restic/releases/download/v0.19.1/SHA256SUMS ZIP SHA256: da948ad707ed690426473aaba2046cd61f8f90f6f0e7dab6be0d5796531de67d 解压后可执行文件 SHA256: b0dd1fd21eea5d8fe1325f55f7118213c21f36de8a261e04c0624a5ab9fd7830 实测版本输出: restic 0.19.1 compiled with go1.26.4 on windows/amd64 ZIP 哈希已与通过同一官方 HTTPS 发布渠道取得的校验值比对。 没有另外验证发布签名。 在新建的工作文件夹中,用 PowerShell 执行: python .\restore-lab.py --restic-zip .\restic_0.19.1_windows_amd64.zip 脚本在工作文件夹中建立全新的 c07-restore-lab-* 目录, 并输出 LAB_ROOT。它不接受已有仓库、源文件夹或恢复位置。 脚本拒绝符号链接和 Windows 重解析点,包括目录联接(junction)。 读取 ZIP 时按字节读取,只提取指定名称的可执行文件。 破坏性测试修改仅限于新建的 S3 仓库副本。 脚本不会自动清理,也不会操作真实数据。 固定的 PUBLIC-SYNTHETIC-LAB-ONLY... 字符串不是秘密, 只是公开测试材料,任何人都能读取。绝不能用它们保护真实文件。 restic 子进程使用这些测试材料,不继承 RESTIC_* 设置。 其临时文件目录位于新建的实验根目录下。 脚本不会修改全局环境变量或 VPN 配置。 结果写入 LAB_ROOT,不会自动复制到用于发布的文件夹。 每次重跑都会创建新的根目录。随机生成的仓库密钥、快照 ID、 数据包 ID 和耗时会变化;要损坏的文件则由已知内容哈希确定。 脚本启动时计算自身源文件哈希,完成时再次检查。 如果运行过程中修改脚本,该次运行就无法完成最终记录。 局限 ---- 正常情况下,这组测试文件总共2,330字节,规模刻意保持很小。 实验不测量大型仓库、恢复速度、硬盘故障率、介质寿命、异地或离线 抗故障能力、云账号找回、凭据保管、完整操作系统恢复、权限、 访问控制列表、备用数据流、应用程序显示效果或未来的格式支持。 解析成功只适用于这些测试文件与指定解析程序。 本实验不能为任何人的实际备份作保证。 相关官方文档 ------------ https://restic.readthedocs.io/en/stable/045_working_with_repos.html https://restic.readthedocs.io/en/stable/050_restore.html https://restic.readthedocs.io/en/stable/030_preparing_a_new_repo.html 公开结果是对0.19.1版本的观察。stable 文档以后可能更新, 因此保留了以上版本输出、发布网址、校验值、命令和源代码。 新增教学资料(2026-09-13) ------------------------- 新的比较脚本会将运行记录与已发布的基准记录进行核对。 文件放置方法、输出含义、适用范围和绘图方法见comparison-readme.txt。 这份技术补充说明和单独的对照图使用英文。