P-256 那串神秘种子,其实是 1997 年的时钟跑出来的

昨天(10 月 16 日)Anthropic 发了篇短文,英文标题是 Claude reveals ECDSA curve origins。Hacker News 当天大概 677 分、272 条评论。中文转发里已经能看到「AI 破解了 ECDSA」「P-256 有后门」这种说法。

先说清楚:原文开头就写了,这事当收尾八卦看就行,没有什么要你立刻改的。不是密码被攻破,也不用去轮证书。多数做密码的人本来就信这些曲线。下面是我读完原文、自己跑过代码之后的记录。

那串 SEED 为什么闹了二十多年

ECDSA 用得很广。NIST 2000 年把一批标准曲线写进 FIPS 186-2。素数域、二进制域上的曲线都会带一个叫 seed 的参数,拿它做哈希,再推出曲线方程里的系数 b。

麻烦在于:这些 seed 当初是 NSA 给的,没说怎么生成。TLS、JWT 里常碰到的 P-256(secp256r1 / prime256v1)长这样:

ini 复制代码
SEED = C49D3608 86E70493 6A6678E1 139D26B7 819F7E90

就一串十六进制。Koblitz 和 Menezes 写过一篇 A Riddle Wrapped in an Enigma,把争议梳理过一遍。社区后来还挂了赏金,谁找出种子来源谁拿钱。

最流行的故事来自已故 NSA 员工 Jerry Solinas 2015 年的回忆:大概是某句玩笑口令的哈希,什么「Give Bob and Jerry a raise」「Bob and Jerry rule」之类。他自己说细节记不清,写代码的 Bob Reiter 也记不清,档案更找不到。Jerry 2023 年去世,这条线基本断了。

Dual_EC_DRBG 之后,公众听到「NSA 给参数又不解释」,很容易往后门上想。从业者那边气氛不太一样。Koblitz / Menezes 2015 年的意思大概是:靠挑种子埋一个二十多年都没人发现的弱点,并不那么好操作。赏金发起人 Filippo Valsorda 后来也写过类似判断。我自己的态度一直偏后者,但也承认:黑箱参数确实不好向人解释。

Claude 怎么找出来的

Anthropic 几个人以前按「口令哈希」搜过,没结果。今年 10 月,有人换了个问法:别猜句子了,想想当年生成曲线的程序大概长什么样。

不到半小时,答案出来了------种子根本不是哈希,是 C 库里的 lrand48。

大致步骤是这样的。先猜 1990 年代常见的弱 PRNG,写扫描器对公布的种子按比特滑动,看相邻块像不像某发生器的连续输出,试了 34 种组合。然后注意到:有些种子写成五个 32-bit 字时,最高位全是 0。这是 lrand48 的脾气------它只吐 48-bit 状态的高 31 位。素数曲线那边,状态恢复是截断线性同余发生器上的老问题,用 LLL 就能做。十个素数曲线种子(含 ANSI X9.62 示例)都对上了同一个模式:lrand48() >> 23。

LCG 可以往前走也可以往后走。把状态退到 srand48 初始化那种形态(低 16 位固定是 0x330E)之后,十个初值全落在 1997 年 5 月到 1998 年 4 月的 Unix 时间戳上。

所以整件事可以压成一行:

srand48(某个时间戳) → 反复 lrand48 → 每 20 字节一个候选 → 取第 n 个。

P-256 对应:

时间 1997-08-16 01:52:34 UTC
时间戳 871696354
候选序号 n 1842
SEED C49D360886E704936A6678E1139D26B7819F7E90

基点 G(曲线上那个固定生成元)也解开了一部分。1997 年 5 月那批六条曲线(P-192 和五条 ANSI 示例)的基点,来自 FreeLIP 的 zrandom(早期 NTL 带过同一段)。做法很土:小整数播种,丢掉前 7 次输出,用 26-bit 输出拼 x 再模 p,直到点落在曲线上。种子是 20000、20420、20507、20509、20512、20517。原文说,据他们所知,这是第一次有 NIST 相关基点被说清楚。

原文里还贴了 Claude 当时的一段内部独白:先怀疑是不是模拟环境,又用「十个种子各 160 bit 对上,不可能是巧合」说服自己。读着挺真实------不是模型突然开悟,是假设换对了,验证又便宜。

几处我觉得对写代码的人有用:

弱 PRNG 会在比特里留指纹。lrand48 最高位恒 0,肉眼都能看出来,但二十五年里几乎没人拿这个角度去扫公开常量。原文给的偶然概率大约是 1/5810(四个相关种子、二十个字的最高位全清零)。

截断 LCG 的状态恢复不是新发明,是教科书。Claude 干的活更像研究助理:把「种子字节可能落在状态的哪段窗口」穷举一遍,每个窗口丢给已知算法。

往回退到 srand48,才把「弱随机」收成「墙上的钟」。单独一个 48-bit 状态不稀奇;稀奇的是十个素数曲线全落回同一类时间戳。二进制曲线那边,初值字面像 1984 年 2 月,时间戳加倍后落在 1998-04-17,紧挨着 P-224 那次运行后两周。原文倾向于「程序可能把时钟除以了 2」,语气是推断,不是定论。

我顺带想:当年要是用了正经 CSPRNG,又不把中间状态漏进可公开对照的常量,这类事后考古会难得多。可复现的生成过程,挑弱实例的空间更小,后来审计也有把手。

我本机跑了一遍

Anthropic 把复现代码以 CC0 放在同一页。今天上午(10 月 17 日,北京时间)我在 Linux x86_64 上原样跑了 reproduce_seeds.py、reproduce_basepoints.py,又写了个只对照 P-256 的小脚本。

素数曲线十个种子的输出,和 Anthropic 文里的表一致。P-256 那一行:

1997-08-16 01:52:34 1842 C49D360886E704936A6678E1139D26B7819F7E90

自己算出来的 got 和 NIST 公布值逐字符相同,打印 MATCH: True。neuromancer.sk 上 P-256 / secp256r1 的 seed 字段也是这串。

基点脚本六条全是 matches published Gx: True。

二进制曲线 B-233、B-283、B-409、B-571 按原文「时间戳可能除以 2」的读法也能复现。B-163 不在表里------原文写了,这个还没解开。

脚本和终端文本在同目录 repro/,有兴趣可以直接跑。

所以,要不要慌?

不要。

Anthropic 原文的口径很明确:这不是一次密码学攻击,也没挖出新弱点。种子是「时钟 + 常见弱 PRNG」这种很朴素的方式生成的,可复现、可审计,反而让「故意埋后门」更难圆。读者不需要因此换证书、换曲线、改线上配置。

Filippo 在认领赏金的博文里算得更硬一点。就算慷慨假设 NSA 能在 1997--1998 任意挑时间戳,再在前 16 个素数阶候选里挑,自由度大概也就 30 bit,够不上 Bernstein / Lange 2017 年讨论过的那种假想弱曲线类(大概要 70 bit 选择自由度)。他说这条技术路径可以排除了。

我会这么读:参数来源说清楚了,日常继续用 P-256 / P-384 没问题。要说「数学上完备证明 NSA 绝对没后门」,那超出了原文。Anthropic 自己还留着开放问题,Filippo 的 30-bit 论证也有前提。对我们做工程的,实用结论就一句------没有新的紧急动作。

别跟 Dual_EC_DRBG 混为一谈。那是另一桩案子,结构里能检验出 trapdoor。这次是种子从黑箱变成了可复现的时钟采样,形态完全不同。

Filippo 文末还有一句个人品味:再加上确定性 / hedged ECDSA、形式化验证的域实现、2015 年 Renes--Costello--Batina 的完整加法公式,他觉得 NIST 曲线这几年的「平反」差不多收束了,就他个人而言甚至会优先推荐它们,而不是 Curve25519 一族------「正好赶在要被后量子签名替下之前」。这是他的选择,不是 Anthropic 的结论,也不是我给你的选型建议。曲线怎么选,还是看威胁模型、库实现和合规。

还没写完的部分

原文列得很老实:

B-163 的种子,Claude 试过的方法都没命中。

P-224、P-256、P-384、P-521 的基点 G 对不上 FreeLIP / zrandom 那套,来源未知。NIST 二进制曲线的基点同样未知。

还有跳过的候选。不是每个 20 字节都能生成合规格曲线,但同一趟里,有些明明合格的也被跳过了。P-256 那趟,第 876 个候选也能给出合适大小的素数阶曲线,最终用的是第 1842 个。P-224 跳过三个,ANSI 示例相关的两趟又跳过七个。筛选标准是什么,或者是不是实现瑕疵,不知道。

Anthropic 的判断:跳过数量不大,不太像在刻意挑弱曲线(那会暗示弱曲线又多又好找)。理论上还能想象有人靠搜时间戳去撞某种性质,可「若你打算靠公开时间戳证明清白,才需要这么做」------而当年并没有公开时间戳。Filippo 复现时还发现,ANSI X9.62 之外似乎还有一条隐含规则:曲线阶 n 的比特长不超过基域 p 的比特长。即便算上这个,合法种子大概仍有已发表数量的两倍,剩下一半为什么弃掉,对不上整齐规律。

这件事也把 AI 的边界露得很清楚。Claude 擅长换假设、写扫描器、认弱 PRNG 的比特模式、把状态恢复丢给已知算法、再对回公开常量。它没有自动补完所有基点,也没有解释跳过规则。半小时解决二十五年悬赏,靠的是角度换对了,加可检验计算------不是模型突然懂了密码学真理。

赏金和出处

Filippo 三年前发起的 NIST 椭圆曲线种子赏金,Anthropic 团队在 2026-10-15 01:07:51 UTC 认领,金额 36,864(36Ki36,864(36 Ki 36,864(36Ki),捐给 Internet Security Research Group(运营 Let's Encrypt 的那家)。署名:John Wood、Henry de Valence、Ava Howell、Zack Voase、Lucy Sweet、Amir Omidi、Paul Crowley、Iain McGinniss、Nicholas Carlini、Steve Weis。文里向 Jerry Solinas 致了悼,也谢了 Filippo。

一手材料(写作时都打开读过):

想自己核对的话,把 Anthropic 那两段 Python 拷下来跑,看 P-256 那行是不是 C49D3608...819F7E90。我已经跑通了。

HTTPS、JWT、不少云 API 签名里的 P-256,不会因为这篇文章突然变「不安全」。有人转成「AI 破解了椭圆曲线」,那是标题党------解开的是参数来源,不是离散对数,也不是签名算法本身。

相关推荐
F&C嘉准传感器1 小时前
FC-SPY抗阳光槽型光电:户外仓储强光不失效,凝露受潮故障减少
安全·目标检测·自动化
刘婉晴2 小时前
【网络安全】OAuth 原理和安全实现
安全·web安全
黄焖鸡能干四碗3 小时前
大数据平台安全防护策略方案(PPT)
大数据·运维·网络·安全·web安全·制造
林伽一3 小时前
端侧模型与运行框架双轮驱动,智能体工程化进入深水区|2026年10月16日
人工智能·科技·安全·ai·开源
Bruce_Liuxiaowei6 小时前
2026年10月第3周网络安全形势周报
安全·web安全·网络安全
是真的小外套16 小时前
第13章:网络安全漏洞防护原理与应用
安全·web安全·php
Ikalus198816 小时前
检查自己写着「这不会让任务失败」:一条 Critical 风险就这么过了 178 天
安全·架构
仿生joe会梦见漫天的大雪吗17 小时前
CTF Misc 工具选型指南:按题型分类的工具、原理与限制
后端·安全
QYR-分析17 小时前
工业安全无线遥控器:5.4% 稳步增长,起重与移动机械的安全控制终端
安全