FIBEMATE 系列。此前讲过迁移动因、混合 HTTPS、CBOM、FPGA 基准、预硅侧信道、TLA+ 形式化验证。这一篇解决一个更基础的问题:你产出的每一份审计证据——TVLA 报告、TLA+ 记录、KAT 结果——怎么证明它在某个时刻就存在、此后没被改过?答案是哈希链 + RFC 3161 可信时间戳 + 可执行验证。工具已开源,仓里躺着 260 份真时间戳(截至 2026-09-27 实测,分散在 40+ 个目录)。
一个典型场景:侧信道评估做完,报告落盘。三个月后有人质疑「这份报告是测试当天生成的,还是后来补的?中间改过没有?」
回答不了。文件系统时间戳可改,git commit 可重写(rebase、重新签名),报告内容对不对得上当时的原始数据,无法证明。
密码工程比一般软件更需要这一层:TVLA 结论、形式化验证记录、KAT 回归结果,都是「某个时刻的状态」的断言。断言没有可信时间锚,审计链条就断在第一步。
解法分三步:把状态快照哈希进链、把链条锚到第三方时间戳、让任何人能在浏览器里重算验证。对应一个工具:crypto-time-ledger(github.com/Lennonhaha/fibemate-tools,Apache-2.0)。
每个账本块(block)记录「某算法在某 commit 下被纳入账本」:
两个设计决定:
tsr_ref 不进哈希,tsr_digest 进。 路径是定位符,挪个目录哈希就变——不行。时间戳文件的 SHA-256 指纹才是内容绑定,块哈希锁住指纹,指纹锁定那份 .tsr。改动时间戳文件一个字节,链条立刻断。
ts 必须与 TSR 时间一致。 块自己声明的时间如果和时间戳服务器签发的不符,链在逻辑上自洽、在事实上造假——验证规则里两者必须对上。
细节一:canonicalize。 哈希前要序列化,而原生 JSON.stringify 不排序键——同一个对象,键序不同,哈希不同,跨语言验证直接失败。所以自实现 RFC 8785 风格的规范化:递归键排序、紧凑输出、UTF-8。还有一个容易漏的细节:RFC 8785 要求 U+2028 / U+2029 转义为 \u2028 / \u2029,原生 JSON.stringify 不转——不处理,JS 和其他语言对同一段数据算出的哈希就不一致。跨实现可验证性死在字符转义上,比死在密码学上常见。
细节二:负例。 演示数据里有一份 TSR(d22f33f6…)签发证书不在信任锚列表内,工具拒绝它、不写进链——这是故意留的负例,验证 fail-closed 行为:任何一项检查不满足,宁可拒收也不放行。信任锚机制是 SPKI DER 逐字节对比已知 TSA 证书列表,不是「信任系统证书库」这种软约束。
RFC 3161 时间戳响应(TSR)是 CMS 结构,验签要解析 ASN.1、比对 messageImprint、验证签名证书链。手写这套解析的风险我们实测过——探索期发现多个具体 bug,ASN.1/CMS 手工解析属于高风险区。最终用 pkijs(成熟库,密码操作委托给平台 webcrypto),自己只写胶水:TSR 加载、eContentType 处理、messageImprint 的 SHA-256 十六进制比对、信任锚 pinning、fail-closed 收口。
当前版本 63 个测试,分布在 7 个套件(ledger add / verify / query / export、全局旗标、stdin、错误格式),文件层面是 cli / core / storage / tsr 四个测试文件,npm test 一条命令跑完(实测 11.5s 全 PASS),CI 挂 ledger 专用 workflow。
工具之外,主仓已经攒下生产证据(origin/main 实测 260 个 .tsr 文件):
位置 | 数量 | 内容 |
|---|---|---|
www/docs/tsa/(按日期序列) | 135 | 线上文档快照、审计记录、FreeTSA 批次 |
docs/tsa/ | 96 | 架构文档、协议验证、事件复盘 |
backend/timestamps/ | 9 | 2026-06 后端 PQC 批次 |
www/docs/tvla/、evidence/tvla/ | 8 | TVLA 侧信道证据 |
www/timestamps/digicert/ | 5 | DigiCert 公共 TSA |
www/docs/evidence/ | 4 | 混合 KEM 验证证据 |
papers/、lib/、fips205/ | 3 | 论文与依赖快照 |
七行合计 260,与总数持平(2026-09-27 实测)。
时间戳来源刻意分散:自建 TSA、FreeTSA、DigiCert——单一 TSA 失效不拖垮整条证据线。
每份证据有 lg- 编号。lg-069 盖的是 2026-07-14 的 K3 形式化验证审计记录,连同 tsq(请求)和 SHA-256 清单一起进 timestamp-manifest.json——三份 manifest(docs、docs/tsa、www/docs)把全部 260 份 TSR 的文件名、大小、指纹登记在册。TLC 跑出「101,467 状态零违反」(其中 26,115 个去重状态)的那次审计,就是 lg-069 盖的章(两个数字官网 cars-radar.html 可查,26,115 distinct 与 2026-09-25 本机复跑 TLC 及 tla-verifier README 记录一致)。
工具页(fibemate.net/tools/time-ledger)做成水墨手卷:每个账本块是一个墨点,青绿为链连续,朱红为链断。「验真整链」按钮在浏览器里用 Web Crypto 逐块重算 hash_now(与 core.ts 同一套 RFC 8785 键排序),校验链连续性与 TSR 附着标记——不装任何东西,打开页面就能验。
演示种子 3 个块全部真实:由 cli.ts add 写入,TSR 来自 test fixtures,逐份验签通过后入链;git_commit 记录工具仓当时的 HEAD,整条链可复现。页面声明写死在开头:demo seed,非生产测量。
系列到这凑齐三条证据线:可观测性管运行时(线上真走了混合路径),TLA+ 管协议逻辑(状态空间无反例),时间账本管存证(证据在何时存在、此后未改)。三条线互相不替代:跑着的不代表验证过,验证过的不代表存了证,存了证的不代表内容对——但四样叠在一起,审计的人就不用再信任何一句「我们做过」。
下一篇换视角:把 git 历史变成密码 API 的可查时间轴——算法参数什么时候改的、谁改的,一条命令查清。
参考实践
crypto-time-ledger/(63 测试,npm test,v0.1.1)fibemate.net/tools/time-ledger(Web Crypto 浏览器验链)fibemate 仓 docs/tsa/、www/docs/tsa/、docs/timestamp-manifest.json词汇注释
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。