2个不稳定版本
0.2.0 | 2022年5月10日 |
---|---|
0.1.0 | 2022年5月10日 |
#1806 in 密码学
135KB
1K SLoC
boo-hoo

一个用于布尔电路的非交互式零知识证明(NIZKPoKs)的库。
这是一个实验性的加密软件:请自行承担风险。
想法是,给定一个程序 P
和一些秘密输入 I
,你可以提供一个证明,表明你知道一些输入 I
,使得输出 O
等于 P(I)
。然后,任何知道程序 P
和声称的输出 O
的人都可以独立地检查这个证明,并且他们会相信你知道这样的 I
。
这是通过ZKBoo方案来实现的。
示例
例如,假设你想要创建一个证明,表明你知道两个秘密位 x0
和 x1
,使得 x0 & x1 == 1
。首先,你需要创建一个代表这个电路的程序
use boo_hoo::*;
use Operation::*;
let raw_program = Program::new([
PushArg(0),
PushArg(1),
And,
PushOutput
]);
电路用基于堆的字节码表示。操作操纵堆上的元素。我们可以用 PushArg
将输入的索引位移动到堆上。我们在程序中使用它来将两个输入位移动到堆上。然后,我们用 And
将它们相与。我们也可以使用 Not
或 Xor
作为其他操作。最后,我们用 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));
其实就这么简单。
详细信息
这是对论文中方案的一个相对直接的实施。事实上,这个实现非常“按部就班”,旨在易于理解,而不是特别高效。操作是按位进行的,这比直接在u32
或u64
上操作要低效得多。在大多数真实程序的实际布尔电路中,比如SHA256
或其他基准测试,你会对这些大块进行布尔操作,通过一次处理多个位可以大大提高性能。
依赖关系
~2MB
~46K SLoC