AEGIS · 第 8 阶段完成

加密藏住的是你说了什么。 这个藏住的是你说过话。

加密让消息的内容保持私密。它藏不住消息发生过这件事。盯着网络看的观察者照样能看到谁在跟谁说话、什么时候说的、搬了多少千字节(KB)— 在敏感场合,这些和话的内容一样要紧。AEGIS 让一个封闭小组成员之间的流量始终以恒定速率流动,不管有没有东西要发,于是时间和流量都不携带任何信号。

语言Rust
对手全局被动
工作区测试195 个通过
模糊测试1.17M+ 次执行
最近一次推送不久前
唯一的规矩

“在攻击模拟确认之前,什么都不算做完。”

开发过程中,关于流量分析的直觉一次又一次地失灵。只有模拟框架被证明靠得住,于是它成了关卡。那套 Python 框架在 sim/ 里,它是规格里每一条量化说法背后的证据台账 — 不是事后补上去给一个已经发布的设计背书的东西。

大白话

一分钟说清这是什么

问题所在

能看到网络的人不需要破解加密。他们看到一个端点在 09:41:03 发出 14 KB,另一个端点三秒后收到 14 KB,而同样的事情连着十一周每天发生两次。重复得够多,这就是一张谁和谁一起工作的地图,画的时候一条消息都没读。

解决办法

AEGIS 让线路上看起来永远一个样。流量以恒定速率发出,不管有没有东西要发;收到的东西被填充到固定大小,所以这一端没有突发可以拿去和那一端的突发对上。它要花带宽,也要加延迟;下面的演示把保护和代价并排摆出来。

这是给谁用的

新闻编辑室,以及任何要保护线人的人:在那里,一次联系的时间和大小才是暴露一个人的东西。互相竞争却还得交换数据的银行、保险公司和行业组织。互相通报攻击预警的机构:在那里,被看见在通报本身就可能是敏感的部分。

藏住内容是容易的那一半。 藏住模式才是需要下面这些工程的那一半:完整的威胁、一个你可以自己对两种配置跑一遍的攻击、测试数字,以及保证到哪里为止。
威胁

能把你认出来的那部分是元数据

全局被动对手读不了你的消息。它也不需要读。它同时盯着每一条链路,然后做关联:这个端点在 09:41:03 发了 14 KB,那个端点在 09:41:06 收了 14 KB,而这个模式每天出现两次,连着十一周。

光靠流量和时间,就足以重建出一整个组织的关系图,一个密码都不用破。对一个联盟来说 — 互相清算的银行、共享病历的医院、有线人的编辑部 — 这张图 就是 那份敏感信息。

AEGIS 把线路变成一堵平坦、不变的墙。不管底下在发生什么,速率恒定,所以流量和时间完全不携带信号。下面这个演示让你对两种配置各跑一次攻击,自己看差别。

模式 1

整形过的混合网络

小而突发的数据,加上全部控制流量。Sphinx 包以恒定速率发出,接收端用硬上限填充,这样接收方的入向流量也是固定的。

模式 2

批量通道

大文件传输,安全级别可调 — 原始、分桶,或者均匀成批。你自己选在成本曲线上待在哪个位置;关于代价,没有任何隐瞒。

交互演示

你来当那个全局被动对手

五个发送方各自只和五个接收方中的一个通信。你只看得到每条链路上的流量大小 — 看不到内容,也看不到路由。把这些序列关联起来,试着把配对还原出来。然后打开恒定速率防御,再试一次。

两种线路特征对比:未整形的流量呈现出可追踪的突发,对手把关系图还原了出来;恒定速率整形过的流量是平的,还原率掉到瞎猜的水平
滑动查看完整示意图 →
对手实际看到的是什么。 下面自己跑一遍攻击 — 这张图里的数字就是那个演示产生的数字。

流量分析框架

发送方链路 接收方链路 相关性,高 相关性,低

对手的结论

正在关联…
 
还原出的配对
—
相关性峰值
—

这项防御的代价

带宽
1.0×
增加的延迟
0 ms

瞎猜的水平是 20% — 五对里猜中一对。明显高于这个数,就是对手赢了。成本那几个数字是老实的另一半:恒定速率整形不是免费的,AEGIS 也不假装它是。

这是为这个页面写的单跳示意。真实系统在这里展示的整形之上,还叠了 Sphinx 路由、守卫节点审核、分布式随机信标和零知识信誉证明。
证据

八个阶段,每一个后面都有一道红队关卡

实现已经完整做到第 8 阶段,也就是加固。下面是仓库报告出来的数字:模糊测试是在适用于 Linux 的 Windows 子系统(WSL)下跑的,测试网跑在真实的传输控制协议(TCP)套接字上。

36/36
密码测试向量
195
通过的工作区测试
1.17M+
模糊测试执行次数,零崩溃
41/41
拓扑测试
领域结果备注
密码向量36 / 36 
中继路由14 / 14 
拓扑41 / 41 
协商器 / 批量相关性25 / 25 
工作区测试195全部通过
安全模糊测试1.17M+通过 WSL 跑 libFuzzer,零崩溃
测试网真实 TCP在真实套接字上做 Sphinx 包路由
轨迹分析良性对恶意真实轨迹对比
这是给谁用的

藏住的是谁在说话,不只是说了什么

把一条消息打乱,这个问题已经解决了。它藏不住的是:你发了一条,发给谁,什么时候发的,发了多少。光是这个模式,往往就足以把人认出来。

01

编辑部,以及任何在保护线人的人

如果能看到某个人在凌晨两点联系了某个记者,那就没人需要读那条消息了。暴露人的是时间和大小。

02

互为对手但仍然得共享数据的公司

银行、保险公司和行业协会一边竞争一边交换信息。你突然开始跟谁通信、多久一次,会把你在做什么泄露出去。

03

互相通报攻击预警的组织

共享威胁情报是有用的,但被人看到你在共享,这件事本身可能就是敏感的。这个把对话发生过这一事实也保住,而不只是保住内容。

在这里看到你自己的情况了吗? 它现在已经开放测试,而它是为哪些人做的,那些人的反馈才是真正会改变它的。 成为测试用户 →
防御措施

整形之上还有什么

  • 前向保密握手。 长期密钥被攻破,不会回溯性地暴露此前的会话。
  • 考虑信誉的路径选择。 路由优先选行为记录已经建立起来的中继。
  • 分布式随机信标。 没有任何单一方控制路径选择的熵。
  • 零知识信誉证明。 中继可以证明自己超过了某个信誉阈值,而不透露自己的分数。
  • 守卫节点审核。 在最要紧的那个点上抵抗女巫攻击。
老实划出的边界

保证到哪里为止

  • 只管内部流量。 强保证只在联盟内部成立。明网出口更弱,也没有声称成别的样子。
  • 是实测出来的,不是证明出来的。 这些结果是在所声明的对手模型下测出来的经验界限。它们不是数学证明。
  • 延迟是与生俱来的。 数秒级的延迟是这个设计的属性,不是一个日后能优化掉的调参问题。
  • 两方通信用错了工具。 AEGIS 适合在很多端点之间隐藏关系图。只有两方的一条链路,用链路层防御更好。
  • 还有没做完的研究。 docs/ops/RESEARCH_AGENDA.md 就是那份老老实实列出还没做完的事项的清单。
仓库卫生: GitHub Actions 上的持续集成(CI),用 cargo deny 做依赖审计,还有一条覆盖整个工作区、禁止 unsafe 代码的规定。对一个要处理敌意输入的 Rust 网络栈来说, #![forbid(unsafe_code)] 贯穿整个工作区,是这个项目里最吃重的一行。