14个版本
0.7.0 | 2024年2月19日 |
---|---|
0.6.0 | 2023年5月8日 |
0.5.1 | 2022年12月16日 |
0.4.1 | 2022年5月6日 |
0.1.1 | 2020年12月18日 |
673 在 密码学 中排名
658 每月下载量
用于 ecdsa_fun
165KB
3K SLoC
SigmaFUN!

一个用于让Sigma协议变得有趣的Rust库!
使用
[dependencies]
# For just the traits and combinators
sigma_fun = {version = "0.6", no-default-features = true, features = ["alloc"]}
# To create secp256k1 non-interactive proofs and serialize them
sigma_fun = { version = "0.6", features = ["secp256k1", "serde", "alloc"] }
# you need a hash function and an rng for non-interactive proofs
rand_chacha = "0.3"
sha2 = "0.10"
应该使用吗?
API和证明的向后兼容性可能随时发生高度实验性和破坏性更改。
尤其是在 ext
模块中更复杂的证明中,很容易出现实现错误!
"Sigma" 协议
Sigma协议是三轮的 诚实验证者零知识协议,是最基本的零知识证明系统之一。由于它们可以通过Fiat-Shamir启发式方法轻松地非交互式化,并且支持各种类型的 组合,因此它们非常有用。Sigma协议可用于构建签名方案、可验证随机函数、身份验证方案、匿名凭证方案以及许多其他奇特的东西。
有关Sigma协议的基本背景,请参阅Shoenmaker的出色讲义的第5节:Shoenmaker。
组合
Sigma协议可以安全地组合在一起,形成一个新的Sigma协议。例如,如果您有两个用于证明陈述 A
和 B
的Sigma协议,则可以将它们组合成用于证明 A or B
的协议。生成的协议也将是一个Sigma协议!目前这个库支持以下组合子
or(A,B)
证明两个陈述中至少有一个是真的。and(A,B)
证明两个陈述都是真的。eq(A,B)
证明两个陈述具有相同的证据(通常A
与B
是相同类型的证明)。all(n,A)
证明了类型为A
的n
个语句都是真实的。eq-all(n,A)
证明了类型为A
的n
个语句都具有相同的证明。
我们缺少对泛化证明 t-of-m
语句是否为真的支持(这要复杂得多)。遗憾的是,目前 all
和 eq-all
中的 n
必须在编译时已知。
《Sigma》特质
此库提供了一个 Sigma
特质,可以为任何 Sigma 协议实现,无论其底层证明结构如何。任何实现了 Sigma
的内容都可以与组合子一起使用,以创建更复杂的 Sigma 协议。最后,可以通过实现 serde
序列化特质,将协议非交互化。
我们使用五个主要核心函数定义了 Sigma
特质
-
gen_announce_secret(rng) -> announce_secret
:从给定的随机数生成器rng
生成用于证明的随机秘密值。 -
announce(statement, announce_secret) -> announcement
:给定要证明的语句以及之前由announcement_secret
生成的announce_secret
,返回一个announcement
。 -
implied_announcement(statement, challenge, response) -> announcement
:确定一个announcement
,使得(statement, announcement, challenge, response, challenge)
是 sigma 协议的一个有效的转储。 -
sample_response(rng) -> response
:从响应空间中均匀抽取响应。 -
respond(witness, statement, announce_secret, announcement, challenge) -> response
:计算对challenge
的有效响应。
每个 Sigma 协议还定义了其 ChallengeLength
作为关联类型。
使用这些算法,交互式 Sigma 协议的执行过程如下
Prover(witness, statement, rng) Verifier(statement)
======
announce_secret = gen_announce_secret(rng)
announcement = announce(statement, announce_secret)
announcement
+------------------->
challenge *uniformly sample ChallengeLength bytes*
<-------------------+
response = respond(witness, statement,
announce_secret, announcement,
challenge)
response
+------------------->
check
implied_announcement(statement, challenge, response)
==
announcement
非交互式证明
使 Sigma 协议非交互式的一种标准技巧是从哈希函数中生成上图中的 challenge
。这被称为 Fiat-Shamir 启发式,在 随机预言机模型 中是安全的。验证者只需检查哈希是否正确计算以及响应是否正确。
示例
佩德森承诺的形式为 C = r * G + c * H
,其中 c
是对 h
的一个值所做的承诺,且 H = h * G
对承诺者来说是未知的。关于佩德森承诺的背景,请参阅 Shoenmaker 第 3.2.2 节。假设我们想向只知道 C
的人证明 c
要么为 0 要么为 1,我们可以通过展示我们知道 r
使得 C = r * G
或 C - H = r * G
来构造一个非交互式证明。
use std::string::ToString;
use sigma_fun::{ typenum::U16, FiatShamir, HashTranscript, Either, Or, secp256k1::{ self, fun::{Point, Scalar, G, marker::*, g}}};
use sha2::Sha256;
use rand_chacha::ChaCha20Rng;
// Pretend to choose H securely in a public setup
let H = Point::random(&mut rand::thread_rng());
// our commitment will be to 1
let c = Scalar::<Secret, _>::from(1u32);
// We use a 16-byte (128-bit) challenge length
type L = U16;
let (C,r) = {
// make a pedersen commitment
let r = Scalar::random(&mut rand::thread_rng());
let C = g!(r * G + c * H).normalize().non_zero().expect("zero is computationally unreachable");
(C,r)
};
// Our strategy is to prove that we know r such that either C = r * G or C - H = r * G using
// an OR composition between two standard knowledge of discrete logarithm proofs.
let statement = (C, g!(C - H).normalize().non_zero().expect("computationally unreachable"));
// since we are commiting to 1 we know the witness for the right hand side statement.
let witness = Either::Right(r);
// Our prover is going to prove knowledge of one of two point to the base G (either C or C - H).
type Protocol = Or::<secp256k1::DLG<L>, secp256k1::DLG<L>>;
// Every protocol has an unambiguous name which is hashed into the transcript for protocol separation purposes.
assert_eq!(Protocol::default().to_string(), "or(DLG(secp256k1),DLG(secp256k1))");
// we want a non-interactive proof system so we apply the Fiat-Shamir transform with Sha256 as the challenge hash.
// We use ChaCha20Rng to help produce our announcement.
let proof_system = FiatShamir::<Protocol, HashTranscript<Sha256, ChaCha20Rng>>::default();
// Make the non-interactive proof -- pass in a system rng to make the proof more robust.
let proof = proof_system.prove(&witness, &statement, Some(&mut rand::thread_rng()));
// The verifier gets sent (C, proof)
{
// The verifier's proof system doesn't need the rng
let proof_system = FiatShamir::<Protocol, HashTranscript<Sha256>>::default();
// They recreate the statement
let statement = (C, g!(C - H).normalize().non_zero().expect("bogus commitment"));
// and verify it against the proof
assert!(proof_system.verify(&statement, &proof));
// The verifier is convinced of the statement and nothing else
}
功能标志
ed25519
:启用 ed25519 离散对数证明secp256k1
:启用 secp256k1 离散对数证明(使用 [secp256kfun])
另请参阅
- ZKP — 该库受到该库的启发,并且发展得更好。
zkp
对散列函数(sha3)和群(ristretto)有看法,并且只支持eq
和and
类型组合。
依赖关系
~0.3–1.7MB
~28K SLoC