2个不稳定版本

0.2.0 2022年5月10日
0.1.0 2022年5月10日

#1806 in 密码学

MIT许可证

135KB
1K SLoC

boo-hoo

一个用于布尔电路的非交互式零知识证明(NIZKPoKs)的库。

这是一个实验性的加密软件:请自行承担风险。

想法是,给定一个程序 P 和一些秘密输入 I,你可以提供一个证明,表明你知道一些输入 I,使得输出 O 等于 P(I)。然后,任何知道程序 P 和声称的输出 O 的人都可以独立地检查这个证明,并且他们会相信你知道这样的 I

这是通过ZKBoo方案来实现的。

示例

例如,假设你想要创建一个证明,表明你知道两个秘密位 x0x1,使得 x0 & x1 == 1。首先,你需要创建一个代表这个电路的程序

use boo_hoo::*;
use Operation::*;

let raw_program = Program::new([
    PushArg(0),
    PushArg(1),
    And,
    PushOutput
]);

电路用基于堆的字节码表示。操作操纵堆上的元素。我们可以用 PushArg 将输入的索引位移动到堆上。我们在程序中使用它来将两个输入位移动到堆上。然后,我们用 And 将它们相与。我们也可以使用 NotXor 作为其他操作。最后,我们用 PushOutput 将堆顶元素移动到输出缓冲区。

我们的程序可能是无效的,例如,从空堆弹出,或访问堆上的未定义元素。因此,我们首先需要验证我们的程序

let program = raw_program.validate().expect("failed to validate program!");

验证方法生成一个ValidatedProgram,该程序已通过明显错误的操作验证,并确切知道程序使用多少输入和输出位。在我们的例子中,程序有两个输入位和两个输出位。

现在,我们可以使用我们的秘密输入为这个程序生成一个证明

use rand_core::OsRng;

let ctx = b"example context";
let input = [0b10];
let output = [0];
let proof = prove(&mut OsRng, ctx, &program, &input, &output).expect("input or output were insufficient")

输入和输出以&[u8]的形式提供。位从切片中的第一个字节开始读取到最低位,从每个字节的最低有效位到最高有效位。如果提供的输入或输出位不足,则证明构建将失败。

我们还传递了一个“上下文”。这个上下文使得证明只能使用该上下文字符串进行验证。这允许将证明绑定到特定的应用程序,甚至绑定到任意消息。如果使用不同的上下文,则证明将无法验证。

现在,我们可以验证这个证明

let result = verify(ctx, &program, &output, &proof);
assert_eq!(result, Ok(true));

其实就这么简单。

详细信息

这是对论文中方案的一个相对直接的实施。事实上,这个实现非常“按部就班”,旨在易于理解,而不是特别高效。操作是按位进行的,这比直接在u32u64上操作要低效得多。在大多数真实程序的实际布尔电路中,比如SHA256或其他基准测试,你会对这些大块进行布尔操作,通过一次处理多个位可以大大提高性能。

依赖关系

~2MB
~46K SLoC