返回文章列表

Post

加密 reasoning 块:重放、侧信道,以及系统提示词能不能抠出来

9 分钟读完

配 OpenClaw 接 Claude 时,thinking 块直接报错:签名校验失败。

thinking 块签名校验错误

思考块里为什么有签名?有签名,多半是在防篡改。顺着看下去,会碰到 OpenAI / Anthropic API 里一类字段:加密后的 reasoning / thinking blob。

reasoning 块是什么

网页 Chat 里看到的“思考过程”,多半只是摘要。真正的 chain-of-thought(CoT)默认不给用户看。

API 不一样。推理模型在 Messages / Responses 接口里,会把 reasoning 或 thinking 字段下发给客户端。里面通常是 Base64,文档写得很死:别解析,下一轮原样带回。

OpenAI reasoning 块结构示意

OpenAI 侧像带认证的密文。有人猜过 Fernet 一类格式,图里有一部分是推测。

Anthropic thinking 块结构示意

Anthropic 更绕。字段名叫 signature,但实测 64 字节那块未必能单独当数字签名验。多个不透明字段绑在一起,改任意一处、跨块拼字段,下一轮就炸。12 字节 IV 有点像 GCM / ChaCha,偏短。

共同点:

  • 密文长度随“想得多不多”涨缩
  • 改密文再回传,API 拒绝
  • 客户端读不懂,但要负责携带

为什么要发给客户端

服务端生成回复时当然看得到 reasoning。问题在于:API 会话不总是服务端长连接。

零保留(zero-retention)、无状态、tool loop、客户端自己维护 transcript 时,服务端不会把完整隐藏状态一直挂在账户会话里。于是它把模型私有状态加密后塞回客户端:你读不了、改不了,但下一轮还能原样交回去,服务端再解密继续推。

这是工程折中,不是故意把秘密送给你。

直接改?改不了

改一个 bit,基本都会被打回来。
光看密文,也看不出明文。

那为什么还要折腾?因为 reasoning 是模型内部独白。OpenAI 在 o1 相关说明里提过:原始 CoT 可能包含他们不想直接暴露的内容。

OpenAI 关于 reasoning 的说明截图

改不动,就换两条路:

  1. 重放:不改内容,换位置 / 换会话 / 换账号塞回去
  2. 侧信道:读长度、token 数、耗时,不读明文

重放:可以,而且跨账号

直接篡改会报错。未修改的旧 reasoning 块,往往可以原样塞回:

  • 同一会话
  • 不同会话
  • 不同账号

OpenAI 上,某些情况下还能跨模型重放;Claude 对跨模型更挑。

密码学上这意味着:provider 很可能用全局密钥(或至少跨账户共享的密钥材料)去加密 / 认证这些 blob,而不是“一会话一密钥、一账户一密钥”。
如果你在用零保留模式,记一笔:大家的 reasoning 状态可能被同一套密钥托管。

应用层还有个更土的坑:
产品若把第三方输入直接拼进 chat JSON,攻击者有机会注入别人的 reasoning 块。服务端若只验密文完整性、不绑会话上下文,后续行为可能被带偏。
处理方式也土:清洗输入,别让用户原样塞 API 结构化字段。

重放了,模型真会“看见”吗

接受密文 ≠ 语义生效。
大量重放会被模型默默吞掉;偶尔会冒出能证明“块里内容被读到了”的输出。

跨会话重放后敏感数字冒出来

左边会话让模型围绕某个 SSN 推理;右边把加密块塞进另一个账号的新会话,同一个数字没怎么提示就冒出来了。说明:

  • 块里确实有可读的语义内容
  • 解密后的内容有时会进入后续上下文

别过度解读。试着让模型“想秘密、别说出来”,再把块搬到新会话,多数时候它仍守口。
能证明的是:你能让模型写进块里的东西,确实在加密容器里。
还不能稳定证明:平台机密 / 系统提示词可以靠重放随便倒出来。

侧信道:长度和耗时会说话

读不了明文,还能看:

  • 加密块有多长
  • reasoning_tokens 一类计数
  • 端到端响应时间

设想 application instructions 里有一个秘密 bit,并写死“绝对不能直接告诉用户”。你仍可要求模型:

  • bit = 0 时做简单计算 A
  • bit = 1 时做极重计算 B
  • 可见输出两边保持一样

模型没有直接说出秘密,但 reasoning 长短会分叉。分类“短 / 长”,就能猜 bit。

按 bit 抽取时的 reasoning 长度分布

上图是把字节 0xA31,1,0,0,0,1,0,1)逐 bit 抽 80 次:每位 10 次,蓝是 0,橙是 1。

只有 chat UI、看不到加密块时,墙钟时间也能干类似的事:

按 bit 抽取时的墙钟耗时

重点不只是“加密 blob 会漏信息”。
更根本的是:只要模型对秘密做了依赖推理,推理本身就可能通过长度 / 时间泄漏。
“求你别说出来”挡得住明文,挡不住计时器。

能不能抠系统提示词

侧信道一通,很自然会想到:
一个字母一个字母地问真假,慢慢凿系统提示词——比如那类“别聊某些设定”的隐藏规则。

实际踩到的坑:

  • API 模式下,GPT / Claude 经常根本没有网页版那种完整 system prompt
  • 模型很乐意编造一个听起来很像的 prompt
  • 实验脚本一旦幻觉,整条链路都会自我证明

能稳定抠的,是你自己塞进 application instructions 的、确实存在的秘密。
抠“模型官方系统提示词”这件事,在 API 路径上常常是在抠一个不存在的对象。
网页版 ChatGPT / Claude 肯定有更厚的系统层,但那是另一条攻击面,这里没往下打。

所以笔记名里的“如何获取封闭的 Anthropic 提示词”,更准的答案是:

  • 靠拆加密 reasoning 块直接读明文:目前不行
  • 靠重放跨会话偷系统提示:证据不足
  • 靠长度 / 耗时侧信道抠应用层秘密:可行,但慢,且依赖你能诱导秘密相关推理
  • API 模式系统提示词:很多时候压根没有你以为的那一份

厂商能怎么收

重放问题相对好补:

  • 密钥按账户 / 会话派生,别全局一把锁
  • blob 绑定 conversation id、user id、model id、回合序号
  • 过期时间 + 防重放计数
  • 文档写清楚:客户端不得跨会话复用 reasoning 字段

侧信道难得多。它不是换加密格式就能消掉的:
只要允许“对秘密做不同计算量的思考”,长度和时间就会说话。硬修可能要在“开始推理前”上策略门;而策略门本身往往也要推理。这是产品、安全和能力之间的拉扯,不是补丁一贴就完。

给应用开发者的清单

  1. 把 reasoning / thinking 当不透明票据,别当日志明文
  2. 用户输入不要直接拼进 API 结构化消息数组
  3. 多租户产品里,禁止客户端跨用户复用历史 reasoning
  4. 别在 instructions 里塞长期有效的高价值密钥;需要密钥就走服务端工具,别让模型“想着密钥做事”
  5. 监控异常:超长 reasoning、异常耗时、同一 blob 高频重放

收尾

加密 reasoning 块说明 provider 把 CoT 当敏感状态在保护。
重放和侧信道说明这层保护还不完整,尤其在密钥绑定和应用输入清洗上。
想靠它一把梭抠出 Anthropic / OpenAI 的封闭系统提示词?现在证据链到不了那儿。
它更像一面镜子:照出的是 API 状态管理方式,以及“隐藏思考”本身有多容易从旁路漏风。