“每个决策都以哈希链的形式写到只追加日志里——智能体无法重写自己的历史。”这是我亲手写下、曾引以为傲的一句话。直到我对着系统做了次完整的审计。
不是哈希链不存在。它存在,只不过毫无意义。
这个问题在自主AI基础设施的宪法安全模型里只是一个切片,但它恰恰击穿了人们对“不可篡改”最朴素的想象。我们总以为加一条哈希链就算筑起高墙,但实际审计拆开看,墙里塞满了空洞。
我用三个不舒服的发现,来还原整件事。不适程度由轻到重。
第一,记账的有两位。那位“良心”——第一版的动作闸门——规规矩矩地写了带链的记录:每条都带着上一条的哈希。可还有第二个组件,负责向外执行动作的家伙,也往同一个文件里追加记录,格式却完全不同,连哈希字段都没有。它每写一笔,都等于在防篡改证据上撕一道口子。日志看起来是只追加的,校验起来却像块瑞士奶酪,到处是窟窿。
第二,两位记账人之间没有锁。两个进程可能同时读到同一个“最新哈希”,然后一同往上追加——一条活生生的分叉。这里甚至不需要什么敌手来攻击。你只是输给了一次竞态条件,这反而更让人后背发凉:没有对手可以抓捕,只有物理定律在安静地指出你的设计有问题。
第三,我们真的发现了坏记录。两条,存储的哈希和内容对不上,时间戳差了几秒,妥妥的并发写入指纹。你看,一份防篡改日志里,竟然真的留下了被篡改过的痕迹,而肇事者,是一个缺失的互斥锁。
一条哈希链,到头来只是简单的那部分。它大概只占到“无法重写历史”这个承诺的五分之一。
真正需要的,是从“追加”往下再沉几层。我们最后做了三件事。
其一,只留一个写者,或者干脆不留。现在所有审计追加都经过同一个实现,拿着排他锁:读头,延链,写入,释放。每一个要记历史的组件都调用同一段代码。单写者这个不变量不是靠约定,而是靠操作系统强制执行的。我们还写了一个测试:让两个进程同时疯狂敲打这个文件,链必须完好无损地走出来。
其二,在链外放一个锚。这里藏着每个天真哈希链的沉默漏洞:谁要是能重写整个文件,就能重算从第一条记录起的每一个哈希,一条假链照样完美自洽。内部一致性证明不了任何历史真相。所以我们让链头周期性地被一个运行时不掌握的密钥签名——公钥放在版本库里,私钥放在审计写者根本访问不到的机密存储中。现在想伪造历史,只想重算哈希已经不够了,你还得伪造签名。链证明的是顺序,签名证明的是这个顺序在某个时刻以前就存在。
其三,真的得有人去验。没人跑的校验等于不存在。所以我们让签名验证成了健康检查的一环,每次决策前都跑一次,每次异常都触发告警。只有把“验证”变成系统呼吸的一部分,防篡改才不是一句说明书上的空话。
这三件事合起来,才从“追加日志”走向了“真正的不可重写”。正方观点会说,哈希链本身在计算机科学里足够坚固,只要正确实现,它就是不可篡改的。反方则会拿这份审计报告拍在桌上:正确实现四个字,在实际分布式系统里重如千钧,一个旁路写入、一个并发冲突就让它形同虚设。
我的判断更靠近反方。哈希链擅长的,是证明一组记录之间的顺序关系;但它不负责保护这组记录不被新增或覆盖。单写者、外部锚定、强制验证这三招,其实是在哈希链的外围,织了一层控制面的网。它们不是为了弥补哈希算法的弱点,而是为了堵住工程实现里那些天然渗漏的缝。
说回“无法重写历史”这句话本身。一开始它是个浪漫的承诺,后来变成了一次物理上的工程训练。你需要的是一个只追加介质,一份不可旁路的写入路径,一个能抵抗回滚的外部锚,以及持续运行的校验程序。这些加起来,才配得上当初那句漂亮话。
如果你的系统也写过类似的保证,不妨同样做一次审计。去查查日志里有没有没带哈希的行,有没有同一个时间戳同时冒出来的两条记录,有没有某个时刻之后的历史可以无痛被整体替换。问题不会藏得很深,它们就静静躺在那里,等你脸红。
这件事提醒了所有搞自主系统、尤其是把审计日志当安全底线的人:不要只信你在白纸上画出来的设计,去信那个凌晨三点还在跑着的实现。哈希链是忠实的,但实现哈希链的世界不是。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.