一位 Anthropic 员工把一道困扰密码学界 25 年的问题丢给 Claude,没说任何线索,模型在不到 30 分钟后给出了答案:NSA 的曲线种子根本不是哈希一…

一道没人能解开的 25 年旧题

NSA 留下的种子,和没留下的答案

2000 年,NIST 在 FIPS 186-2 标准中采纳了五条椭圆曲线:P-192、P-224、P-256、P-384、P-521。这些曲线用于 ECDSA 数字签名,至今仍在比特币、TLS 等场景大量使用。

每条曲线都附有一组被称为「种子」的起始参数。标准流程是:对种子做哈希,哈希结果参与确定曲线系数。种子公开了,但 NSA 没有说明它们是怎么来的。

没有生成过程,没有选择依据。一串数字摆在那里,解释权归 NSA 所有。

「后门」猜测从何而来

密码学界的第一反应是怀疑。Neal Koblitz 和 Alfred Menezes 在 2015 年的论文里把这称为「一个谜中之谜」。怀疑的逻辑很简单:如果 NSA 测试了大量候选曲线,从中挑出具有隐藏弱点的参数,那它完全可以只公布最终选择,不公布筛选过程。

流传最广的传说是 Jerry Solinas 对一句玩笑话做了哈希。有人说可能是「Give Bob and Jerry a raise」。安全研究员 Steve Weis 花了数年追查,包括 2018 年提交公开记录请求。NIST 说没有文档,NSA 停止了回应。

2023 年,加密工程师 Filippo Valsorda 提供 12,288 美元奖金悬赏答案,若获奖者捐赠慈善机构,总额可超 36,000 美元。Solinas 已在当年去世,研究者只能依靠旧时回忆和数字本身推敲,没有结果。

被追着问 BUG 修完了吗时的程序员表情

Claude 开始搜索 90 年代的软件工具

`%% title: 谜题形成路径

NSA 提供种子

NSA 提供种子

程序员系列表情:你别急,等我剪完这个头发再修Bug

真相锁定

没有线索,从零排查

这道题的难处在于,你没有任何方向。2000 年,NIST 在 FIPS 186-2 标准中列出了五条标准椭圆曲线,每条曲线都带有一组被称为「种子」的参数。NSA 提供了这些种子,但公开文件从未说明生成过程。

外界因此长期担心:设计者是否曾筛选大量候选曲线,并从中挑出具有某种隐藏性质的参数?2015 年,密码学家 Neal Koblitz 和 Alfred Menezes 在他们的论文中把这称为「一个谜中之谜」。

流传最广的说法是,NSA 工程师 Jerry Solinas 对一句玩笑话做了哈希。有人甚至悬赏 12288 美元寻找答案。Solinas 已于 2023 年去世,研究人员只能依靠旧时的回忆和数字本身进行推敲,但一直没能得出结果。

搬砖系列表情:见鬼,难道这帮人都不用搬砖的吗

工地搬砖

Claude 的做法完全不同。它没有去搜索那句可能被哈希的玩笑话,而是换了个角度:猜程序用了 1990 年代的弱伪随机数生成器。

这个思路的关键在于,它跳出了「人是故意设计」的框架,转而考虑「人是随便写的代码」的可能性。坦白讲,这种假设在密码学界并不讨喜——大家更愿意相信 NSA 做了精密的计算,而不是随手调了一个 C 语言库函数。

最高位全是 0 的信号

一个线索立刻脱颖而出。五条曲线中,有四条二元曲线的种子的 20 个 32 位字,最高位全是 0。

随机出现这种情况的概率约为 5,810 分之一。这不是巧合,而是特征。

程序员反应图:程序员00052 放肆怎么跟程序员说话呢

代码评审折磨

C 语言的 lrand48 函数正是这样的行为:它返回 48 位随机数的 31 个最高位,最低位被截断。这意味着生成的数字最高位永远为 0。

这个观察直接指向了 lrand48。相比之下,如果种子是通过哈希函数生成的,最高位应该是均匀分布的,不会出现这种系统性的偏置。

从 lrand48 的特征倒推状态

确认了生成器,下一步就是倒推初始状态。

对于二元曲线,Claude 用了枚举法:尝试所有可能的 17 位隐藏状态,看哪个能复现已知种子。对于素数曲线,它用了 LLL 格算法恢复状态。输出模式为 lrand48() >> 23。

状态倒推回 srand48 初始化形式后,真正的发现出现了:10 个素数曲线种子全落在 1997 年 5 月到 1998 年 4 月之间的具体日期。

P-192 对应 1997 年 5 月 18 日,其他几条曲线也各自对应不同的日期。你买的旗舰款,瞬间变成平替套餐——这里的「旗舰款」是神秘的后门阴谋,「平替套餐」只是随手用的系统时钟。

Claude 自己的推理记录写道:「这太令人震惊了:它解开了这个延续了 25 年的谜团。」

程序员系列表情:666

成功起飞

整个过程耗时不到 30 分钟。没有暴力搜索,没有启发式猜测,只有对数据特征的冷静分析和对时代背景的准确判断。

真相:时间戳,不是秘密短语

五条曲线,五个具体日期

Claude 的推理链条在两条线索上同时收敛。

第一条线索来自二元曲线。五条 NIST 曲线中,P-224 和 P-256 属于二元域曲线,其种子由 20 个 32 位整数组成。Claude 检查了这 20 个整数的最高位,发现全部为 0。这种模式随机出现的概率约为五千八百分之一,几乎可以排除巧合。

这正是 lrand48 的特征。C 标准库中的 lrand48 函数返回一个非负长整数,其实现方式是将 48 位内部状态右移 16 位后再取低 31 位,因此结果的最高位(第 31 位)始终为 0。其他常见伪随机数生成器,比如 glibc 的 rand(),返回值覆盖完整的正整数范围,不会出现这种规律性的全零高位。

第二条线索来自素数曲线。P-192、P-384 和 P-521 的种子由单一整数表示,无法通过位模式直接判断来源。Claude 转而使用格基约化算法 LLL(Lenstra–Lenstra–Lovász)进行逆向推导,将种子值映射回 lrand48 的内部状态序列。算法输出的模式显示,种子等于 lrand48() 右移 23 位的结果,与 C 标准库的实际实现完全吻合。

两条独立线索都指向同一个生成器。这不是一个猜测,而是两个不同维度的证据交汇。

从 1997 年 5 月到 1998 年 4 月

倒推内部状态之后,下一步是还原 lrand48 的初始种子。C 语言中,lrand48 通常由 srand48() 初始化,后者接收一个 32 位的输入值。

Claude 恢复出的初始化值全部落在 1997 年 5 月至 1998 年 4 月之间,且每个值精确对应一个具体的 Unix 时间戳。以 P-192 为例,恢复出的时间戳对应 1997 年 5 月 18 日。其余四条曲线的时间戳分别落在 1997 年 6 月、7 月、10 月以及 1998 年 4 月。

一条曲线用一天,五次生成,跨度十一个月。这个节奏与 NSA 工程师在不同时间分别生成不同安全级别曲线的假设一致,也解释了为什么五条曲线的种子看起来完全独立——它们从来就不是同时生成的。

Jerry Solinas 生前曾提到种子可能来自一句玩笑话的哈希值,比如「给 Bob 和 Jerry 加薪」。Claude 没有沿着这个方向搜索。它从一个程序员会用什么工具生成随机数的角度切入,而那个年代的程序员,最可能用的就是 lrand48。

更狠的是,每年能省下一个亿的猜测,最后发现答案只是一串普通的日期。

这次发现的意义和边界

把种子来源搞清楚,不意味着有人在算法里埋了陷阱,也不意味着有人把陷阱拆了。它改变的是我们对「谁在什么时候用了什么方法」这件事的判断权重。

没有攻破 ECDSA,也没有新攻击

这里需要先说清楚一件事,因为标题很容易让人误读。这条发现没有给 ECDSA 带来任何新的攻击路径,没有找到可以绕过 P-256 签名的捷径,也没有让已有的破解方案变得更高效。Claude 做的事是溯源,不是破译。

具体来说,它做的事情可以分成三步:先识别出种子数据里隐藏的结构特征,再通过数学推导还原 lrand48 的内部状态,最后把状态倒推出初始化时间戳。每一步都是可复现的确定性计算,不需要额外的假设,也不需要 NSA 提供内部文档。

这也是为什么安全社区的反应相对平稳。如果这次发现的结论是「这些种子存在可被利用的弱点」,那整个数字签名基础设施都会重新评估。但它给出的结论是「种子来自一个公开的伪随机数生成器和一组普通日期」,这个结论本身不提供攻击路径。

更准确地说,lrand48 确实是一个弱生成器,它的状态空间只有 48 位,理论上可以被暴力还原。但那些种子是在 1997 年到 1998 年之间生成的,当时选择曲线参数的过程本身并不需要抵御现代意义上的计算能力,它只需要满足「看起来随机」这个基本要求。我们今天能还原时间戳,不代表当时的 NSA 工程师有意为之。

这有点像是你翻出十年前的日记本,发现里面写了一个密码,然后用今天的算力一秒就解开了。密码本身从未被威胁过,它只是刚好放在了一个对当前技术条件太弱的地方。

「后门」嫌疑大幅降低

25 年来,关于这些种子的主要猜测是:NSA 在生成过程中筛选择了大量候选曲线,从中挑出了一条只有他们知道如何攻破的「特制曲线」。这种猜测的逻辑链是完整的——如果种子是用强随机源加上哈希生成的,外部人员确实无法验证设计者是否做过筛选。但反过来看,这种猜测也永远无法被证伪,因为它缺乏可检验的证据。

Claude 的发现打破了这个僵局。种子可以用 lrand48 和时间戳完整复现,这意味着任何人都有机会验证「这条曲线真的是按这个流程生成的」。当复现过程不需要额外的假设,也不需要访问任何内部文档时,「人为刻意筛选」这个假设的解释力就大幅下降了。

当然,这不是绝对的证据。严谨地说,仍然存在一种可能性:NSA 用 lrand48 生成了大量候选曲线,然后从其中挑选了一条,只是恰好这条曲线在当前分析框架下表现正常。但这个可能性随着时间推移在缩小——距离种子生成已经过去了近三十年,期间密码学界对椭圆曲线的理解深化了很多,如果真的存在一条被刻意弱化的曲线,早该有其他研究路径暴露出来。

[["reaction:detective-truth|caption=线索终于对上了"]]

一个值得注意的细节是,Jerry Solinas 生前曾暗示种子可能来自一句玩笑话的哈希,比如「给 Bob 和 Jerry 加薪」。这个假说曾被很多人验证过,但始终没有找到匹配的哈希值。Solinas 2023 年去世后,这条路就彻底堵死了。Claude 没有找到任何哈希痕迹,而是直接定位到了 lrand48 的输出模式。真相不是某个精心设计的幽默,而是一个程序员随手敲了一下 srand48(time(0))。

为什么这件事值得记一笔

这件事的价值不在于它改写了密码学,而在于它展示了一种新的研究范式。过去 25 年里,关于这些种子来源的探索主要靠两种方法:一是文献调查,追查当时的通信记录和会议材料;二是穷举搜索,尝试各种可能的短语组合和哈希函数。这两种方法都依赖对历史档案的可访问性,而 NSA 的文件并不对外公开。

Claude 走了一条完全不同的路。它没有去查档案,也没有去猜短语,而是从种子数据本身的结构出发,把问题变成了一个模式识别和逆向工程的任务。最高位全是 0 这个信号,对人工分析来说可能只是一个统计异常,但对模型来说是一个明确的函数特征指纹。

这意味着什么?意味着当一个领域的问题长期卡在「证据不足」上时,换一种分析方法可能比增加更多假设更有效。不是所有悬案都需要更多线索,有时候需要的是更精准的观察角度。

[["reaction:programmer-daily|caption=线索对上了,故事讲得通了"]]

收尾:今天能做什么

这条发现对绝大多数用 ECDSA 的人来说,不影响任何现有决策。P-256 目前没有已知的安全缺陷,继续用它签名没有问题。如果你的系统使用的是 NIST 推荐的曲线族,不需要因为这次发现做任何紧急调整。

但从更长远的角度看,有两个方向值得记录:

第一,如果你正在评估一套加密方案的信任基础,优先选择那些参数生成过程完全透明、不依赖任何机构背书的方案。Ed25519 就是这样一个例子,它的种子生成逻辑公开可见,不存在类似的来源争议。

第二,如果你们团队内部有基于模糊历史文档做安全判断的情况,不妨试一次逆向分析优先的思路——先从数据本身的特征出发,而不是从「设计者可能做了什么」出发。Claude 解开这道题的路径,本质上就是把问题从意图推断转向了结构还原。

参考文献

点这里一键关注『计算机魔术师』

如果浏览器无法直接唤起微信,可在微信内打开公众号主页:计算机魔术师

上一篇:
Nathan Lambert 质疑 OpenCode 事件中蒸馏一词被滥用
下一篇:
从六个月路线图到JIT规划:代码评审不只是审代码

分享到这些地方