混淆(第二部分):Diamond IO

Hacker News Top 新闻

摘要

Vitalik Buterin 解释了一种名为 Diamond iO 的新型密码学混淆技术,它依赖于更大胆的假设,将运行时间从“星系级”降至“行星级”,有望使混淆更接近实际应用。

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

缓存时间: 2026/07/31 10:56

# 混淆(第二部分):Diamond iO 来源:https://vitalik.eth.limo/general/2026/07/28/obfuscation_part_ii_diamond_io.html 2026 年 7 月 28 日查看所有文章(https://vitalik.eth.limo/index.html) 混淆(第二部分):Diamond iO*特别感谢 Sora Suegami 和 **Janmajaya Mall 的反馈与审阅。* 在本系列上一部分中,我们完整梳理了密码学混淆(iO)协议中最主流、最保守的技术路线。这些协议允许你“加密”程序,使得任何人都可以在明文输入上运行“加密”后的程序并获得明文输出,而无法看到程序的内部逻辑。这可以用于各种用例,尤其是当程序内部包含某个秘密密钥时,混淆能够实现这样的目标:给某人一个包裹,让它能*在某些情况下*用秘密密钥*做某些事情*,但除此之外不能做任何事。 迄今为止,这些协议最大的缺点在于其极其离谱的“星系级”运行时间——如果你真的尝试计算运行其中一个协议需要多长时间,你会得到一个比宇宙寿命还长的答案。因此,尽管近期在可行性上取得了突破,混淆协议目前仍只是理论上的奇珍异宝。 本文将详细描述一种不同风格的混淆:diamond iO(论文(https://eprint.iacr.org/2025/236),演讲(https://simons.berkeley.edu/talks/sora-suegami-ethereum-foundation-machina-io-2025-06-24))。这种方法依赖于“更大胆”、更未经检验的密码学假设,但它实现的只是“行星级”而非“星系级”运行时间——目前仍然不可行,但也许只需再经过几次优化,至少可以为少数几个用例变为现实。 *不同类型的混淆* ## Diamond iO 是如何工作的? 在高层次上,diamond iO 是通过修改 BGG+14 属性基加密(ABE)方案(上一篇文章(https://vitalik.eth.limo/general/2026/06/29/obfuscation1.html#attribute-based-encryption-abe)中已介绍)而构建的。我强烈建议在继续之前重新阅读那一节。 *也不是这位 Abe。如果你知道这位 Abe 是谁,给你加分——比上一篇文章中的那四位要难!* 与更传统的 iO 协议一样,diamond iO 在 ABE 内部使用 FHE 执行计算,然后只在计算确实是正确计算结果的条件下,给求值者一种解密结果的方法。但 diamond iO *使用*这套机制的方式不同。首先,它使用了一种完全不同的机制来做有条件的 FHE 解密。其次,它使用了一种完全不同的机制来生成输入的编码。 这两个修改是相互关联的,也是 diamond iO 能够更加高效的根本原因——它“只是”与函数加密计算强度相当,而不是在函数加密之上建立更复杂的塔。 提醒一下,BGG+14 的工作方式是维护如下形式的编码: \\\(s \* \(B \- G \* m\) \+ e\\\) 其中: - \\\(s\\\) 是一个秘密 - \\\(B\\\) 是一个公开矩阵,电路中的每条“导线”都有一个不同的 B - \\\(m\\\) 是计算过程中该导线上的比特 - \\\(e\\\) 是一个“误差” (另外,你也可以加上 \\\(G \* m\\\) 而不是减去;两者都能得到同样有效且高效的方案) 给定两个代表某个运算——无论是加法、乘法还是取反——的两个“输入导线”的 \\\(B\\\) 矩阵,你可以生成一个代表输出导线的 \\\(B\\\) 矩阵。给定运算两个输入的合法编码,你可以得到输出的编码——\\\(1 \- m\\\)、\\\(m\_a \+ m\_b\\\) 或 \\\(m\_a \* m\_b\\\)——它基于代表输出导线的 \\\(B\\\) 矩阵。重要的是,这不是全同态加密:要做乘法,你需要知道 \\\(m\_a\\\) 或 \\\(m\_b\\\) 的明文。 在 BGG+14 中,最后有一个步骤,允许解码一个预先选定的输出,但仅当计算中某个“输出”导线上的值等于 0 时才允许。这里我们不这样做。相反,我们要做的只是从编码中提取我们需要的数据。但在两种情况下,解密方法都依赖于编码基于代表输出导线的特定矩阵 \\\(B\_\{final\}\\\)——这就是我们如何强制要求,只有当你正确地执行了计算时才能解密,而在任何其他情况下都不能解密。 diamond iO 的核心是: - 生成表示输入 \\\(x\\\) 的 BGG+14 \\\(B\\\) 矩阵和编码,外加一些其他东西 - 在这些 BGG+14 编码上运行一个计算,将 \\\(x\\\) 转换为一个*FHE 密文* \\\(FHE\.enc\(f\(x, z\)\)\\\),其中 \\\(f\\\) 是公开的,而 \\\(z\\\) 是混淆器试图隐藏的内部秘密输入 - 运行另一个稍作修改的 BGG+14 步骤来 FHE-解密输出 - 最后,做一个“陷门”步骤,借用与 BGG+14 解密类似的机制,但以非常不同的方式来使用它,从而得到结果——仅限于当你运行的是“正确”电路的情况下 diamond iO 的复杂性集中在三个方面: - 你最终对输出编码所做的处理,使得只有在所计算的电路与表示 \\\(f\\\) 的电路完全相同时才能进行这种 FHE 解密,同时又不完全泄露密钥 - 对 \\\(f\(x, z\)\\\) 进行一些调整,以考虑到这样一个事实:整个方案只有在 FHE 解密输出看起来是完全均匀分布的随机值时才是安全的;然后将其从“混淆 \\\(f\(x, z\)\\\) 以隐藏 \\\(z\\\)”转换为“完整 iO 以隐藏程序” - 如何让求值者构造输入的 ABE 编码,而又不泄露秘密。 前两个想法来自先前的工作,尤其是 HLL23(https://eprint.iacr.org/2023/1716)和 AKY24(https://eprint.iacr.org/2024/1719)。第三块,即构造输入 ABE 编码的机制,最初来自 GGH15(https://eprint.iacr.org/2014/645);diamond iO 的新贡献在于,不是用它来求值整个程序(这被证明是不安全的),而是用它来生成输入的 BGG+ 编码。 我们将依次处理这三块。 ## 解密步骤 暂时假设求值者*以某种方式*获得了以下四类 BGG+ 编码的输入: - \\\(1\\\)(这对后面构造这些编码会有帮助) - \\\(f\\\) 的固定隐藏输入的 FHE 加密结果,记为 \\\(z\\\)(我们将加密后的版本记为 \\\(E\[z\]\\\)) - 公开输入比特:\\\(s \* \(B\_\{x\_1\} \- x\_1 \* G\) \+ e\_\{x\_1\} \.\.\. s \* \(B\_\{x\_L\} \- x\_L \* G\) \+ e\_\{x\_L\}\\\), 其中 \\\(x\_1 \.\.\. x\_L\\\) 是 \\\(f\\\) 的输入 - 一个 FHE 解密密钥(必须是低范数,且最后一个值必须为 -1),我们称之为 \\\(t\\\) 我们将这一组记号标记为 \\\([1, E\[z\], x, t\]\\\)。 求值者首先使用 \\\(E\[z\]\\\) 和 \\\(x\\\) 的编码运行 BGG+ 计算。记住,计算不是 \\\(f\(x, z\)\\\) 本身,而是 \\\(FHE\.eval\(f, x, E\[z\]\)\\\)。从 BGG+ 的角度来看,\\\(x\\\) 和 \\\(E\[z\]\\\) 都是明文比特。从 FHE 的角度来看,\\\(z\\\) 是一个隐藏输入,求值者只知道它的加密形式。 在做完 BGG+ 计算后,求值者拥有代表表示 \\\(f\(x, z\)\\\) 的 FHE 密文的各个比特的 BGG+ 编码。 BGG+ 不是全同态加密;一般来说,对 BGG+ 编码进行计算需要知道底层的明文。但我们可以对*加法*,以及对*与已知值相乘*来绕开这条规则。这是因为 \\\(m\_a \* m\_b\\\) 的 BGG+ 编码是通过下式计算的: \\\(c\_\{out\} = m\_b \* c\_a \+ c\_b \* G^\{\-1\}\(B\_a\)\\\) (如果编码是*加上* \\\(G \* m\\\) 而不是减去,那么就是 \\\(G^\{\-1\}\(\-B\_a\)\\\)) 我们可以允许 \\\(m\_a\\\) 是未知的(即只通过编码给我们),只要 \\\(m\_b\\\) 是已知的。 这对我们来说是一个重要的事实。为了理解为什么,回想一下 GSW 解密的结构(也在这个系列的上一篇文章(https://vitalik.eth.limo/general/2026/06/29/obfuscation1.html#fully-homomorphic-encryption-fhe)中介绍过): 因为求值者知道实际执行轨迹的所有比特,包括最终的 FHE 密文(我们称之为 \\\(Y\\\)),我们可以只以 BGG+ 编码的形式给求值者 FHE 解密密钥 \\\(t\\\)。 我们来看看解密是如何工作的。 我们想要计算 \\\(t \* Y\\\)。我们只有 \\\(t\\\) 的 BGG+ 编码,而 \\\(Y\\\) 既有 BGG+ 编码又有原始比特。所以原则上我们可以做到。 但有一个问题:\\\(Y\\\) 是以一系列比特的形式给我们的。也就是说,我们得到的不是形如 \\\([2, 6, 11...]\\) 的向量。我们得到的是形如 \\\([0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1...]\\) 的向量,其中每组比特(在这个例子中是 4 个比特)是一个数的二进制编码,按惯例低位在前。所以我们必须以某种方式重新缩放这些比特,使得在每一个我们做 BGG+ 乘法的单元格中,\\\(t\_j \* Y\_\{\\\{i,j,b\\\}\}\\\),其中 \\\(Y\_\{\\\{i,j,b\\\}\}\\\) 是单元格 \\\(Y\_\{\\\{i,j\\\}\}\\\) 中阶数为 \\\(2^b\\\) 的比特,输出的编码按 \\\(2^b\\\) 缩放。 为了方便,我们把相同阶数、且最终会在答案中落到同一个值里的比特编码分组在一起:也就是说,对于某个特定的 \\\(i\\\) 和 \\\(b\\\),所有 \\\(j\\\) 上的整列 \\\(t\_j \* Y\_\{\\\{i,j,b\\\}\}\\\)。 \\\(\\sum\_j s \* \(B\_\{\\\{out,i,j,b\\\}\} \- t\_j \* Y\_\{\\\{i,j,b\\\}\} \* G\) \+ e\_\{\\\{out,i,j,b\\\}\}\\\) \\\(= s \* \(B\_\{\\\{out,i,b\\\}\} \- \(tY\)\_\{\\\{i,b\\\}\} \* G\) \+ e\_\{\\\{out,i,b\\\}\}\\\) 现在我们到了谜题的关键:我们如何将不同阶数的比特组合在一起? 一个天真的做法可以是直接重新缩放然后相加: \\\(\\sum\_\{b=0\}^\{log\(q\)\-1\} \(s \* \(B\_\{\\\{out,i,b\\\}\} \- \(tY\)\_\{\\\{i,b\\\}\} \* G\) \+ e\_\{\\\{out,i,b\\\}\}\) \* 2^b\\\) 问题在于,这样会把高阶数字的误差放大太多:最高阶项的误差会被乘以 \\\(2^\{log\(q\)\-1\} = \\frac\{q\}\{2\}\\\),从而淹没整个范围。 所以我们改为这样做: \\\(\\sum\_\{b=0\}^\{log\(q\)\-1\} \(s \* \(B\_\{\\\{out,i,b\\\}\} \- \(tY\)\_\{\\\{i,b\\\}\} \* G\) \+ e\_\{\\\{out,i,b\\\}\}\) \* G^\{\-1\}\(2^bG\)\\\) \\\(G^\{\-1\}\(2^bG\)\\\) 在这里完成了所有的工作。基本上,这是一个***按桶左移的运算符***——它把每个 \\\(log\(q\)\\\) 比特的桶 \\\(tY\\\) 全部向左移动。 记住,BGG+ 编码的形式是 \\\(s \* \(B \- G \* m\) \+ e\\\)。还要记住 \\\(G\\\) 的形式如下: 这意味着 BGG+ 编码在*每个尺度上同时*编码了 \\\(m\\\)。而我们在这里做的是,把高阶比特的更高尺度编码移动到每个桶的第一列。而且因为我们只是做加法和移位,而不是乘法,所以避免了误差爆炸,误差只会因为加法而增加很小的量。 为了理解为什么 \\\(G^\{\-1\}\(2^bG\)\\\) 有这种移位效果,我们再看一下 \\\(G^\{\-1\\}\)。单独来看,\\\(G^\{\-1\\}\) 是 \\\(G\\\) 的右逆,是*比特分解算子*(不是矩阵)。 因此,普通的 \\\(G^\{\-1\}\(G\)\\\) 就是单位矩阵: 但如果我们先把 \\\(G\\\) 乘以 \\\(2\\\) 再放进 \\\(G^\{\-1\\}\\\),每个二进制分解就会向上移动一位,于是我们得到了想要的移位: 这只是一个记号技巧,使得“每个桶左移”的机制能够容易地编码到向量-矩阵代数中。还要注意到 \\\(G^\{\-1\}\(2^bG\)\\\) 矩阵显然也是低范数的(只有 1 和 0);这也是知道这一步不会不合理地放大误差的另一种方式。 这一步的最终结果是,你得到 \\\(tY\\\) 的 BGG+ 编码: \\\(s \* \(B\_\{\\\{final,i\\\}\} \- G \* \(tY\)\_i\) \+ e\_\{\\\{final,i\\\}\}\\\) 注意,这些不再是“正常”的编码,因为 \\\(\(tY\)\_i\\\)'s 是模 q 的全范围值,也因为求值者不知道这些明文值。求值者不能对它们做进一步的 BGG+ 乘法。但这没关系,因为它们不需要再做;求值者剩下的唯一步骤是去掉“用 \\\(s\\\) 包裹”的过程,以便达到最终目标:提取 \\\(\(tY\)\_i \+ e\\\)。 为了提取 \\\(\(tY\)\_i \+ e\\\),我们将完全偏离 BGG+ ABE。在 ABE 中,我们知道在应当能够解密的情况下,答案 \\\(C\(tag\)\\\) 等于 0,\\\(G \* C\(tag\)\\\) 消失,这正是我们能够提取消息的原因。\\\(G \* C\(tag\)\\\) 扮演的是*盲化因子*的角色。在这里,用例不同:\\\(\(tY\)\_i\\\) 正是我们想要提取的全部内容。 让我们把 BGG+ 编码重写为: \\\(s \* B\_\{\\\{final,i\\\}\} \- s \* G \* \(tY\)\_i \+ e\_\{\\\{final,i\\\}\}\\\) 现在,从这个表达式中提取一列——最后一个桶中的最低阶列。 \\\(s \* b\_i \- s \* g \* \(tY\)\_i \+ e\\\) 选择最低阶列与“传统 GSW 解密”不同,传统做法是提取最高阶列;但记住:由于我们的按桶移位技巧,现在最低阶列包含了从代表我们最关心的值(消息)的最高阶列中抓取的信息。 我们约束 \\\(s\\\),使得它的最后一个值(我们记为 \\\(s\_\{last\\}\\\))等于 -1。另外,注意我们选择的 \\\(G\\\) 的列 \\\(g\\\) 只是一堆 0 后面跟一个 1。因此,我们得到一个简明化简的表达式: \\\(s \* b\_i \- s\_\{last\} \* \(tY\)\_i \+ e\_i\\\) \\\(= s \* b\_i \+ \(tY\)\_i \+ e\_i\\\) 现在,我们的任务是计算 \\\(s \* b\_i\\\),以便将其移除。 我们从后面一个小节引入一个事实:求值者能以一种编码样本的形式“访问”\\\(s\\\):\\\(ct = \(m \\otimes s\) P\_L \+ e\_L\\\),其中 \\\(m\\\) 是混淆计算的全部输入,\\\(\\otimes\\\) 是“张量积”。也就是说,\\\(m \\otimes s\\\) 是一个长度为 \\\(len\(m\) \* len\(s\)\\\) 的向量,其中先是 \\\(s\\\) 乘以 \\\(m\\\) 中的第一个值,然后紧接着是 \\\(s\\\) 乘以 \\\(m\\\) 中的第二个值,依此类推。方便的是,\\\(m\\\) 中的第一个值被固定为 1。 现在,我们使用上一篇文章 ABE 部分(https://vitalik.eth.limo/general/2026/06/29/obfuscation1.html#attribute-based-encryption-abe)中描述的陷门机制,来制作一个低范数原像 \\\(K\_G\\\),满足: \\\(P\_L \* K\_G = M\\\) 这里,\\\(M\\\) 是一个矩阵,包含*所有* \\\(b\_i\\\)'s——即从每个 \\\(B\_\{\\\{final,i\\\}\}\\\)矩阵中提取的列——然后用额外的零填充,以使维度匹配。 这保证了 \\\(ct \* K\_G\\\) 求值为 \\\(\(\(m \\otimes s\) \* P\_L \+ e\_L\) \* K\_G\\\) \\\(= \(m \\otimes s\) \* P\_L \* K\_G \+ e\_L \* K\_G\\\) \\\(= \(m \\otimes s\) \* M \+ e\_g\\\) 现在,注意到 \\\(M\\\) 中只有前 \\\(len\(s\)\\\) 行是非零的,而 \\\(m \\otimes s\\\) 中的前 \\\(len\(s\)\\\) 个值就是 \\\(s\\\)。因此,上式化简为: \\\(s \* M \+ e\_g\\\) 这正是我们需要的所有 \\\(s \* b\_i \+ e\_\{\\\{i,g\\\}\}\\\)的拼接。 现在,我们可以减掉它,得到我们需要的 \\\(\(tY\)\_i \+ e\_i\\\) 值,也就是我们的 FHE 解密结果。最后,求值者进行舍入,得到最终值。

相似文章

混淆:打造密码学的终极Boss

Lobsters Hottest

一篇文章讨论混淆作为一种强大的密码学原语,因其理论和实践上的挑战,可能成为密码学的‘终极Boss’。

探究加密推理块

Hacker News Top

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

Fool's Gold(阅读时间18分钟)

TLDR AI

本文介绍了'Fool's Gold',一种防御性欺骗技术,它训练开放权重模型在面临安全移除攻击时生成带有伪造关键元素的诱骗响应,从而有效毒化攻击收益。在多个模型上测试,该技术实现了高诱骗率,且未降低良性性能。

不透明串行深度的操作化(3分钟阅读)

TLDR AI

本文档操作化了一种称为“不透明串行深度”的度量,以量化AI模型中的未语言化串行认知,提出基于自然语言的节点作为可解释的瓶颈,以增强对潜在推理的监督。