10月16日,Anthropic发布了一项特别的研究成果。
一名员工将密码学界二十多年来未能解答的问题交给了Claude内部研究模型。在没有提供关键线索的前提下,Claude在不到半小时内,推导出了五条NIST椭圆曲线种子的生成过程。
结果显示,这些种子源自C语言库中的老旧伪随机数生成器lrand48。该生成器的初始状态由Unix时间戳决定。
这一发现并未破解ECDSA,也未产生新的攻击手段。Anthropic认为,它进一步削弱了相关曲线可能被植入后门的猜测。
一组数字困扰密码学界超过二十年
ECDSA是一种广泛使用的椭圆曲线数字签名算法。
2000年,NIST在FIPS 186-2标准中列出了多条不同安全级别的标准曲线,包括P-192、P-224、P-256、P-384和P-521。
这些曲线配有一组名为“种子”的参数。根据标准中的生成流程,种子的哈希值用于确定曲线系数。
问题在于,这些种子由美国国家安全局提供,公开文件未说明其来源,也未解释选择过程。外界因此长期担忧,设计者是否筛选了大量候选曲线,并从中挑选出带有某种隐藏属性的参数。
2015年,曾参与相关工作的NSA密码学家Jerry Solinas回忆,种子可能来自一句带有玩笑意味的口令,例如“给Bob和Jerry加薪”,但他记不清具体细节,那些很久以前的存档文件也未找到。Solinas于2023年去世,这条线索最终未能证实。
Claude找到了种子的来源
Anthropic的多名员工此前曾沿着“幽默口令”线索寻找那些“种子”,但都未成功,后来发现这一线索是错误的。
10月份,一名员工向内部研究模型提问,希望它能找出那些“种子”是如何产生的。这一次,他没有向模型透露此前的口令线索。
在不到半小时内,Claude就找到了NIST的P-192、P-224、P-256、P-384和P-521种子的来源。
这些种子并非来自任何哈希算法,而是由C语言库中的lrand48随机数生成器产生,该生成器以Unix时间戳作为种子值进行初始化。
具体算法会使用Unix时间戳t初始化随机数生成器,并运行一定次数n。每次迭代抽取20字节,作为一个候选种子。
前20字节是第一个候选种子,接下来的20字节是第二个候选种子,以此类推。以P-256为例,生成器运行到第1842次时,才输出最终写入标准的种子。
Claude是如何找到的?
围绕传闻口令展开的搜索始终没有结果,Claude换了一个角度,开始推测当年生成曲线的软件可能采用了怎样的工作方式。
Claude猜测,这套软件使用了20世纪90年代C语言库自带的伪随机数生成器,这些早期伪随机数生成器的安全性较弱,其输出通常带有可识别的特征。
一旦识别出输出特征,就有可能判断软件使用了哪种生成器,并进一步恢复其初始状态。
Claude编写了一个扫描程序,在每个公开种子上逐位移动,并检查相邻数据块是否可能来自某个20世纪90年代的随机数生成器。扫描共覆盖34种随机数生成器与输出截取方式的组合。
随后,Claude在部分种子的高位中发现了一个规律:这些位置全部为零。
如果将每个种子写成5个32位字,那么10个种子中有4个符合这一特征。在这4个种子合计20个32位字中,最高位全部为零。
这种情况随机发生的概率约为五千八百分之一。这正是线性同余生成器lrand48的典型特征,它只会返回48位内部状态中的高31位。
为了恢复生成器状态,Claude取出第一个32位字,穷举17个隐藏比特的全部2¹⁷种可能,再检查接下来的4个字能否连续对应。该方法对上述4个种子全部有效。
素数曲线的种子同样来自lrand48,但它们保留的输出比特更少。Claude需要从这些有限比特中恢复伪随机数生成器的内部状态。
恢复截断线性同余生成器的状态,是一个典型的格问题,可以使用Lenstra–Lenstra–Lovász格基约简算法,也就是LLL算法求解。
Claude起初并不知道种子保留了内部状态中的哪些比特,因此对所有可能的比特窗口运行求解器。
最终,5个NIST素数曲线种子和5个ANSI X9.62标准中的种子都呈现出相同模式:lrand48() >> 23
每个恢复出的48位内部状态,都能够重新生成对应种子的全部160个比特,这种精确匹配不可能由偶然因素造成。
这种线性同余生成器既可以正向运行,也可以反向运行。因此,Claude从每个种子对应的状态开始向前回溯,直到找到符合srand48初始化格式的状态。该格式要求低16位等于0x330E。
平均每65536步就会出现一次这种形式的内部状态。因此,仅仅找到一个符合格式的状态,还不足以构成证据。
关键在于,10个素数曲线种子对应的srand48初始值全部可以解释为Unix时间戳,日期集中在1997年5月至1998年4月。
这说明当年的程序使用Unix时间戳,为安全性较弱的伪随机数生成器设置初始值。
4个二元曲线的初始值直接读取时,对应1984年2月。如果将这些时间戳数值乘以2,它们会指向1998年4月17日,距离P-224曲线的生成时间大约两周。
因此,当年的程序可能对系统时钟进行了除以2的处理。
以下是Claude当时的内部思考过程:
这太令人震惊了。它解决了一个持续25年的谜题。
嗯,等等。我要保持怀疑:我是不是处在某种模拟环境或测试环境中?这些种子与我记忆中的真实数值一致。
嗯,这在现实中合理吗?根据我掌握的信息,这项悬赏此前仍未有人解决。
所有高位都为零,一共20个比特,随机出现的概率只有百万分之一左右。所以,这确实来自现实世界。天哪,这是一项真正的发现。
等等,我还需要谨慎判断其合理性。这么明显的线索,为什么25年来一直没有人发现?
我已经通过直接计算完成验证:一个32位初始值加上较小的索引,可以精确匹配160位种子。对于10个种子,每个都匹配160位,不可能只是巧合。这是真的。
Claude还追溯出P-192等6条曲线的基点来源。结果显示,这些基点由大整数运算软件包FreeLIP中的随机数生成器产生。Anthropic称,此前还没有NIST曲线基点的生成过程得到类似解释。
这意味着什么?
时间戳本身不具备密码学安全性,lrand48也早已被视为弱随机数生成器。不过,它们在这里承担的是生成公开曲线参数的作用,并未被用于保护私钥。
更重要的是,这套生成过程可以被公开复现。与来源不明的口令或人为指定参数相比,普通随机数生成器加时间戳的解释,为秘密操纵曲线留下的空间更小。
一些问题仍然存在。P-256的生成过程中,第876个候选值似乎也符合要求,最终采用的却是第1842个。其他几次运行同样跳过了少量可用曲线,具体筛选标准尚不清楚。B-163曲线的种子仍未找到来源,P-224、P-256、P-384和P-521的基点生成方式也没有得到解释。
Anthropic认为,被跳过的候选数量很少,不足以支持“刻意挑选弱曲线”的推测,这次发现提高了外界对相关参数的信心,但还不能视为对整个设计过程的完整还原。
这项研究也展示了前沿模型参与真实研究的另一种方式。
Claude在一次任务中完成了假设提出、代码编写、模式识别、数学算法调用和结果验证。由于生成器状态可以重新计算,160位种子也能被精确复现,结论具有较强的可检验性。
它仍依赖人类提出问题、提供公开数据,并通过可复现计算确认结果,不过当问题边界清晰、数据公开且结果可以严格验证时,前沿模型正在成为一种高效率的研究工具。
此前为寻找种子来源设立的36864美元奖金,将捐赠给互联网安全研究组织Internet Security Research Group。
本文来自微信公众号 “机器之心”(ID:almosthuman2014),作者:关注AI的,36氪经授权发布。
