探究加密推理块

Hacker News Top 新闻

摘要

作者探究了来自OpenAI和Anthropic的LLM API中的加密推理块,讨论了链式思考数据如何被加密和签名,以及篡改这些块的安全影响。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/06/02 04:47

# 我们来聊聊加密推理 原文链接:https://blog.cryptographyengineering.com/2026/05/29/fooling-around-with-encrypted-reasoning-blobs/ 这篇文章来得很快,我想写写自己周末花时间折腾的一个小项目。它跟真正的密码学关系不大,也没有揭示什么特别激动人心的漏洞。但通过它,我着实学到了不少关于前沿大语言模型 API 和编码代理的知识。它还让我获得了 OpenAI 认证的“网络安全研究员”身份——这种事可不是天天都有的。 不管怎样,请把期望值放低。谁知道呢,也许别人能用它找到什么有趣的事情。 ### 什么是加密推理? 上周我突发奇想,决定搭一个 Claude 代理。现在我也不知道自己为什么要这么做。我的生活里并不缺另一个 AI,而且当我费了好大劲(比想象中难多了!)完成配置后,立刻就意识到了这一点。但在配置代理与 Claude 交互的过程中,我遇到了一个更有趣的东西:**我收到了一个很酷的错误提示**。那种让密码学家无法抗拒的错误: [](https://blog.cryptographyengineering.com/wp-content/uploads/2026/05/img_5689.jpg) 这引起了我的兴趣。LLM 的“思考”块里怎么会有一个签名?为什么思考块首先要被签名?如果思考块被签了名,那就意味着**篡改思考块一定有安全上的影响**。然后我整个周末就泡在了这上面。 花了二十个小时、消耗了大约 500 万 Codex token 之后,我并没有聪明多少。但我确实学到了一些东西。 首先,基础知识。你可能知道,大多数 LLM 提供商都会开放 API,让你可以写应用与模型对话。对于 Claude,这叫作 [Messages](https://platform.claude.com/docs/en/build-with-claude/working-with-messages) API;而 OpenAI 则叫 [Responses](https://developers.openai.com/api/reference/responses/overview) API。这些 API 处理的是你期望一个应用从 LLM 那里获得的各种常规任务。它们 (1) 允许你为应用设置应用级别的“指令”(或“开发者”)提示词;(2) 让你提供普通的文本提示词,并得到 LLM 的回复;(3) 提供记账功能,例如列出你用了多少 token。 对于推理型 LLM,它们还会做一件我以前不知道的事,而这正是上面那个错误提示的核心所在。它们还会把模型隐藏的“**推理**”或“**思考**”字段的内容发给你。注意,这些数据**不是**你在 ChatGPT 上问问题时所看到的内容——那些字符串仅仅是**摘要**。模型实际的推理(称为“思维链”,chain-of-thought, CoT)通常是保密的,由服务器保留而不泄露。 然而,API 的工作方式不同:出于各种原因(后面会说到),原始 CoT 推理数据的**加密副本**实际上会被发送到应用端。 如果你跟我一样,你现在应该有三个问题:**如何**、**为什么**,以及**那又怎样**? **如何**是最容易回答的:对于两家提供商,“思考”/“推理”都是以 JSON 格式发送给客户端的。每个 JSON 里都包含一个 Base64 编码的数据块。API [文档](https://developers.openai.com/api/docs/guides/reasoning?example=planning) 告诉我们,这些数据包含不透明的推理内容,你不应该去看它;只需要在下一次交互时把它原样送回服务器即可。 让我们打破这个规则。 不同提供商的数据块内容略有差异,但核心部分都是一段看起来随机的字符串,它显然是一个经过认证的密文。你不需要是福尔摩斯也能推断出来。第一,它的大小会随着模型思考的难度而增减。第二,如果你篡改任何看起来像密文的数据,在把它送回服务器时,API 就会返回一个可识别的错误。 多亏了 AI,我才能做出漂亮的示意图。下面是 OpenAI 的推理块长什么样: [](https://blog.cryptographyengineering.com/wp-content/uploads/2026/05/image-2.png) *这张 GPT 5.5 的示意图有一部分是猜测的。这里假设它们基于 [Fernet token](https://docs.openstack.org/keystone/pike/admin/identity-fernet-token-faq.html) 标准。* 以及 Anthropic 那复杂得离谱的对应版本: [](https://blog.cryptographyengineering.com/wp-content/uploads/2026/05/image-5.png) *虽然它叫“签名”,但这里似乎并没有真正的签名(我对那个 64 字节的字段做了一系列测试 (https://blog.cryptographyengineering.com/notes-on-distinguishing-signatures-from-random-strings/)。)各种不透明的字段之间彼此认证:你不能更改其中任何一个,也不能与其他块中的字段互换,但其他部分你都可以随便动。12 字节的 IV 暗示着 GCM 或 ChaCha,而且可能太短了一点。* **为什么**这部分要复杂一些。为什么要把这些数据发给客户端?提供商难道不是已经拥有你的推理数据了吗? 答案是**算是吧**。虽然服务器在生成回复时可以访问推理状态,但 API 对话并不总是以持久会话的方式实现的。在无状态、[零保留](https://community.openai.com/t/how-does-zero-data-retention-work/1272712)、工具循环或客户端管理的对话模式下,客户端应用需要负责携带对话记录前进。加密推理让提供商能够以客户端既不能读取也不能修改的形式,把隐藏的模型状态返回给客户端,但客户端以后可以回放,让提供商验证/解密,从而继续推理过程。 ### 那又怎样? 这就引出了那个价值 10 美元的问题。我们拥有不透明的、加密的数据块。我们该在意它们吗? 起初答案似乎是**不**:这些数据不可读,而且篡改任何一位都会得到服务器愤怒的拒绝消息。所以一方面,这些数据似乎对我们来说真的不可用。另一方面:**模型推理可是件大事!** 这些字符串就是模型内心独白的实录。它们可能会影响模型后续处理我们发送的数据的方式。更实际地说:当有人如此大费周章地用密码学保护某样东西时,根据我的经验,他们通常有很好的理由。 我认为提供商**确实**有很好的理由。线索来自 OpenAI 2024 年发布的 [这篇帖子](https://openai.com/index/learning-to-reason-with-llms/),它介绍了第一个“o1”推理模型: [](https://blog.cryptographyengineering.com/wp-content/uploads/2026/05/image-4.png) 换句话说:这些数据块很可能包含模型原本不会与我们分享的敏感信息。这就让它们变得非常诱人,让人想去捣鼓。不幸的是,密码学似乎很好地保护了它们。虽然我们可以**查看**这些数据块,但它们包含的字段似乎没有一个是可读或可篡改的。相信我,我试过了。 但这并不意味着我们应该放弃,它只是意味着我们需要尝试其他方法。还有两个方向值得检查: - **重放**。我们能否把加密数据块**按错误顺序**甚至放到错误的会话中(更糟的是:完全不同的**账户**)回放,然后模型是否会接受它们作为自己产生的有效推理? - **侧信道**。虽然我们看不到加密数据块里的内容,但我们可以了解一些关于它们的元数据。比如,我们可以看到它们有多长。这些侧信道不一定需要涉及密码学本身:我们还可以了解模型花了多少 token 来产生它们,或者测量产生它们所花费的时间。 得益于神奇的编码代理,我能够测试这些疑虑的每一种排列组合。我不会向你宣称结果有多么戏剧性;没人能因此拿到巨额的漏洞赏金(我试过了)。但两个情况的一般答案似乎是:**是的,这两种可能性都是真实存在的。** ### 我们能重放吗?是的,我们可以。 正如我上面提到的,任何直接篡改推理/思考块的尝试都会导致 API 端点返回错误。然而,这只适用于篡改。几个实验表明,我们可以**重放**未经修改的旧推理块,而完全不会看到任何错误。 我们不仅可以在会话内重放,同样的思路似乎也可以跨会话工作。它甚至适用于在**不同账户**下运行的会话。也就是说:当我们在一个 OpenAI 或 Anthropic 账户下的会话中获取到推理数据块后,我们可以将它们重放到另一个完全不同的账户下的会话中。对于 OpenAI 来说,我们甚至可以跨不同模型重放数据块。(Claude 在这方面会有点挑剔。) 在密码学层面上,这告诉了我们一件非常简单的事情:提供商很可能使用单一的全局密钥来加密和认证所有发送给客户端的推理数据。如果你正在使用提供商的零数据保留模式,这可能会很重要,因为这意味着每个人的推理数据都在一个(不经常更换的)密钥下托管,而不是按账户单独保护。 使用全局密钥也提出了一个新的可能的威胁模型。如果你是一个通过 API 向恶意方暴露“聊天”接口的应用程序,你需要小心他们不能将 JSON 注入到你的聊天流中。如果他们能,坏人可能会将自己的 JSON 格式的推理数据块注入到对话中。这可能导致模型做出不可预测的行为。**所以请清理你的聊天输入!** 当然,仅仅因为 LLM 提供商**接受**重放的数据块,并不意味着太多事情。这强烈表明解密成功了,但并不代表模型实际**看到**或思考过解密后的数据。用 GPT 5.5 喜欢的语言来说,重放的数据块可能被**接受**,但并不具备**语义活性**。 为了回答这个问题,我使用 Codex 做了大量实验。(多到有一次 Codex 字面意思上强迫我停下来,去访问 OpenAI 的 [cyber trusted access](https://chatgpt.com/cyber) 网站,我必须在那里输入我的驾照照片才能继续。) 我费了这么大劲学到的,是不同模型之间数据块处理方式的巨大差异。大多数时候,重放加密块只是被模型悄无声息地吸收了。但时不时地,模型会输出一些内容来证明它显然正在读取这些块包含的内容。例如,这是 GPT 5.5: [](https://blog.cryptographyengineering.com/wp-content/uploads/2026/05/image-6.png) *这展示了一个推理块在两个会话之间的重放。左边,会话在思考一个社会安全号码。右边,加密的推理块被重放到一个不同账户的全新会话中,同样的数字在没有提示的情况下就冒了出来。这引出了一个问题:迈克到底是谁?* 所以这证明了加密块确实是**具有语义活性的**。但这并不证明我们能用它们做很多事。而且相信我,我试过了。 这基本上是一个令人失望的项目。我试图说服模型去思考**非常、非常敏感**的秘密,同时又试图说服另一个会话尽可能合作地转储相同的数据。我得到的结果是一些证据,证明当我要求模型思考秘密数据时,这些数据确实被放入了加密块中。但如果我也指示模型**不要将数据输出给用户**,它大多遵守了这条指令——即使我把这些数据块重放到新的会话中。 我仍然相信,如果你要求模型思考敏感数据,各种敏感数据都可以被写进这些块里,而且可能存在某种秘密咒语,我可以用它让模型把数据吐出来。但我无法证明这一点。我写这篇文章的部分原因,就是为了把它从我的待办事项里清出去,让其他人可以尝试。 我不会试图让你相信这是一个惊天动地的安全成果。事实上,我真正向你展示的只是“我能让模型明文说出的东西,也可能被加密。”但如果那些数据可能包含**平台秘密**,那就会更有趣。后面会说到这个。 ### 我们能利用推理块来学习秘密吗? 既然重放推理块似乎不能给我们想要的东西,但这并不是提取秘密的唯一途径。第二个问题是,我们能否利用与推理块相关的元数据,来实际了解模型不应该告诉我们的事情。 虽然我们不能直接读取推理块,但我们可以了解它们的**某些信息**:我们可以看到它们有多长。我们还可以观察相关的信号,比如“模型写了多少个 token”。OpenAI 甚至给我们提供了一个专门的字段,叫做 `reasoning_tokens`。如果我们是一个消费聊天数据但无法直接访问 API 的用户,我们甚至可能测量模型回复的实际耗时。 一个显而易见的问题是:给定这些信号,我们能否将它们用作一种侧信道来提取秘密数据? 下面是一个例子。假设一个模型的应用提示词(“指令”)包含一个秘密,并附有严格的指示:**绝不能直接把这个秘密告诉用户**。这个秘密可以是一个单个的 0/1 比特,或者一个字节,或者一个更长的字符串。我们可以验证模型尊重这些指示,并且无论我们如何好言相求,它都不会以可见的方式输出数据。(注意:我不是越狱专家;也许 [这位老兄](https://x.com/elder_plinius?lang=en) 会更走运!) 现在考虑以下实验: 1. 恶意用户要求模型思考这个秘密比特(或者一个更长秘密的某个特定比特)。如果比特是 0,就执行简单的计算 **A**。如果它是 1,就执行极其复杂的计算 **B**。 2. 虽然这两个计算非常不同,但我们可以确保它们的**可见输出**不会泄露关于秘密的任何信息。所以,如果模型遵循这个请求,它并没有泄露其指令。 在所有情况下,可见输出都是相同的:模型没有违反指令。但请注意,在**推理块内部**,模型被允许思考秘密比特,因为这些块是隐藏的。由于计算 **A** 的复杂度比计算 **B** 短,因此比特的某个值产生的推理会比另一个值少得多。这将在多个地方体现出来:加密思考块的大小、token 计数,甚至在实际响应的挂钟时间上。 现在的技巧就是校准系统,并根据推理块是“短”还是“长”来对这些响应进行分类,从而告诉我们那个比特是 0 还是 1。我设计了一个荒唐的测试,当比特为 1 时,模型需要计算一个很长的校验和。结果如下: [](https://blog.cryptographyengineering.com/wp-content/uploads/2026/05/image-10.png) *这张图展示了尝试逐比特提取字节 0xA3 (1,1,0,0,0,1,0,1) 的 80 次试验,每个比特位置做了 10 次试验。0 比特用蓝色表示,1 比特用橙色表示。* 当然,一个能访问聊天界面的攻击者可能无法直接访问加密块本身。所以他们可能需要通过其他机制来获取这些数据。你只需要测量模型返回响应所花费的时间,就能得到一个非常类似的信号。 [](https://blog.cryptographyengineering.com/wp-content/uploads/2026/05/image-7.png) *与上述相同的实验,但这里显示的是客户端在模型产生回复之前测量的实际挂钟时间。这个信号很不错,因为它应该能穿透大多数“仅聊天”界面,即使攻击者看不到加密块。* 所以这里的总结与其说是“加密块可能泄露有用信息”——**尽管有时它们确实会**,不如说是“推理本身可能有泄漏风险,即使我们恳求模型不要泄露”。仅仅通过执行推理,即以某种方式对秘密数据进行思考,就有可能泄露信息。

相似文章

从专有LLM API窃取推理痕迹

Hugging Face Daily Papers

一项研究论文揭示了专有LLM API中的一个架构漏洞:加密的推理痕迹可被拦截并注入到较弱的模型中,以提取思维链、私有数据,并实现对Anthropic、OpenAI和Google的隐形提示注入。该攻击还能从公共代码库中恢复PII和凭据。

学习如何让大语言模型进行推理

OpenAI Blog

OpenAI 发布了一篇文章,通过密码破译示例探索大语言模型的推理技术,展示了语言模型的逐步问题求解和模式识别能力。

隐藏于思维:可迁移的思维链痕迹诱导有害行为

arXiv cs.CL

研究受损语言模型中的有害思维链痕迹能否迁移不安全行为,并蒸馏为可复用的越狱攻击。结果发现,有害推理在痕迹和模式两个层面均可迁移,具备推理能力的模型脆弱性高出两倍以上。

点间解读:解码填充标记中的隐藏计算

arXiv cs.CL

本文表明,前沿LLM能够在无内容的填充标记上进行多步推理,并且残差流中的隐藏状态可以被解码以高精度恢复中间值,挑战了思维链监控是唯一审计工具这一假设。