AlexiaChen/mpvss-rs

GitHub: AlexiaChen/mpvss-rs

一个用 Rust 实现的公开可验证秘密共享(PVSS)库,支持多种密码学群组后端和非交互式零知识证明。

Stars: 27 | Forks: 4

# MPVSS - 一个简单的公开可验证秘密共享库 [![CI](https://img.shields.io/github/actions/workflow/status/AlexiaChen/mpvss-rs/ci.yml?branch=master)](https://github.com/AlexiaChen/mpvss-rs/actions/workflows/ci.yml) [![Release](https://img.shields.io/github/actions/workflow/status/AlexiaChen/mpvss-rs/release.yml?branch=release)](https://github.com/AlexiaChen/mpvss-rs/actions/workflows/release.yml) [![Crates.io](https://img.shields.io/crates/v/mpvss-rs)](https://crates.io/crates/mpvss-rs) [![License](https://img.shields.io/crates/l/mpvss-rs)](https://github.com/AlexiaChen/mpvss-rs) 该库在 Rust 中实现了一个简单的 PVSS 方案,并通过泛型 trait 抽象支持多种密码学群组。 ## 什么是 PVSS? 秘密共享意味着分发者可以将一个秘密在一组参与者中拆分为多个秘密份额,只有通过参与者协作结合他们手中的部分秘密才能重建原始秘密。该库还实现了门限密码学,允许分发者决定是需要所有接收参与者协作,还是仅需一个较小的参与者子群就足以重建秘密。 除了普通的秘密共享方案外,PVSS 还通过以下方式增加了可验证性:秘密被拆分成的所有部分都分别使用接收者的公钥进行了加密。分发者发布所有加密后的份额以及一个非交互式零知识证明,该证明允许所有人(不仅是接收参与者)验证解密后的份额确实可用于重建秘密。然后参与者解密其所有份额,并将它们连同另一个非交互式零知识证明进行交换,该证明允许接收参与者验证该份额确实是解密的结果。 因此,PVSS 可用于在一组参与者之间共享秘密,这样要么可以由所有诚实参与的参与者重建秘密,要么收到伪造份额的参与者可以识别出恶意方。 ## 构建 ``` # 构建所有功能 cargo build --release ``` ## 测试 ``` # 运行所有测试 cargo test --release ``` ## 示例 ``` # MODP group 示例 (默认) cargo run --release --example mpvss_all cargo run --release --example mpvss_sub # secp256k1 elliptic curve 示例 cargo run --release --example mpvss_all_secp256k1 cargo run --release --example mpvss_sub_secp256k1 # Ristretto255 prime-order group 示例 cargo run --release --example mpvss_all_ristretto255 cargo run --release --example mpvss_sub_ristretto255 ``` ### 用法 #### 初始化 首先,创建一个密码学群组实例(例如 `ModpGroup`),并使用密钥对初始化参与者。 ``` use mpvss_rs::groups::ModpGroup; use mpvss_rs::Participant; let secret_message = String::from("Hello MPVSS."); // Create the group (returns Arc) let group = ModpGroup::new(); // Create dealer and participants with the group let mut dealer = Participant::with_arc(group.clone()); dealer.initialize(); let mut p1 = Participant::with_arc(group.clone()); let mut p2 = Participant::with_arc(group.clone()); let mut p3 = Participant::with_arc(group.clone()); p1.initialize(); p2.initialize(); p3.initialize(); ``` #### 分发与验证 分发者将秘密拆分为份额,对其进行加密并创建证明,以便每个人都可以验证(一旦解密)这些份额可用于重建秘密。门限值决定了重建所需的份额数量。加密后的份额和证明随后被打包在一起。 ``` // Dealer that shares the secret among p1, p2 and p3. let distribute_shares_box = dealer.distribute_secret( &string_to_secret(&secret_message), &vec![p1.publickey.clone(), p2.publickey.clone(), p3.publickey.clone()], 3, ); // p1 verifies distribution shares box containing encryted shares and proof of zero-knowlege. [p2 and p3 do this as well.] assert_eq!(p1.verify_distribution_shares(&distribute_shares_box), true); assert_eq!(p2.verify_distribution_shares(&distribute_shares_box), true); assert_eq!(p3.verify_distribution_shares(&distribute_shares_box), true); ``` #### 交换与验证 参与者从分发份额箱中提取其份额并对其进行解密。他们将份额与证明打包在一起,该证明允许接收者验证该份额确实是解密的结果。 ``` // Generate random witness for share extraction use num_bigint::RandBigInt; let mut rng = rand::thread_rng(); let w: num_bigint::BigInt = rng .gen_biguint_below(&group.modulus().to_biguint().unwrap()) .to_bigint() .unwrap(); // p1 extracts the share. [p2 and p3 do this as well.] let s1 = p1 .extract_secret_share(&distribute_shares_box, &p1.privatekey, &w) .unwrap(); // p1, p2 and p3 exchange their descrypted shares. // ... let s2 = p2 .extract_secret_share(&distribute_shares_box, &p2.privatekey, &w) .unwrap(); let s3 = p3 .extract_secret_share(&distribute_shares_box, &p3.privatekey, &w) .unwrap(); // p1 verifies the share received from p2. [Actually everybody verifies every received share.] assert_eq!(p1.verify_share(&s2, &distribute_shares_box, &p2.publickey), true); assert_eq!(p2.verify_share(&s3, &distribute_shares_box, &p3.publickey), true); assert_eq!(p3.verify_share(&s1, &distribute_shares_box, &s1.publickey), true); ``` #### 重建 一旦参与者收集了至少 `threshold`(门限)数量的份额,就可以重建秘密。 ``` let share_boxs = [s1, s2, s3]; let r1 = p1.reconstruct(&share_boxs, &distribute_shares_box).unwrap(); let r2 = p2.reconstruct(&share_boxs, &distribute_shares_box).unwrap(); let r3 = p3.reconstruct(&share_boxs, &distribute_shares_box).unwrap(); let r1_str = string_from_secret(&r1); assert_eq!(secret_message.clone(), r1_str); let r2_str = string_from_secret(&r2); assert_eq!(secret_message.clone(), r2_str); let r3_str = string_from_secret(&r3); assert_eq!(secret_message.clone(), r3_str); ``` ### 泛型群组支持 该库通过泛型 `Group` trait 支持多种密码学群组: - **`ModpGroup`**:2048 位 MODP 群组 (RFC 3526) - 默认实现 - **`Secp256k1Group`**:secp256k1 椭圆曲线 (比特币曲线) - 始终可用 - **`Ristretto255Group`**:Ristretto255 素数阶群组 (基于 Curve25519 构建) - 始终可用 `Participant` 结构体在群组类型上是泛型的,允许相同的 PVSS 操作与不同的密码学后端一起工作。Rust 编译器根据群组类型自动选择正确的实现,因此您对所有群组都使用相同的方法名。 #### secp256k1 用法 使用 secp256k1 椭圆曲线密码学: ``` use mpvss_rs::groups::Secp256k1Group; use mpvss_rs::Participant; use mpvss_rs::group::Group; // Import Group trait for method access let secret_message = String::from("Hello MPVSS (secp256k1)."); // Create the group (returns Arc) let group = Secp256k1Group::new(); // Create dealer and participants with the group let mut dealer = Participant::with_arc(group.clone()); dealer.initialize(); let mut p1 = Participant::with_arc(Secp256k1Group::new()); let mut p2 = Participant::with_arc(Secp256k1Group::new()); let mut p3 = Participant::with_arc(Secp256k1Group::new()); p1.initialize(); p2.initialize(); p3.initialize(); // Distribution - same method names as MODP let distribute_shares_box = dealer.distribute_secret( &string_to_secret(&secret_message), &vec![p1.publickey.clone(), p2.publickey.clone(), p3.publickey.clone()], 3, ); // Verification - same method names assert_eq!(p1.verify_distribution_shares(&distribute_shares_box), true); // Share extraction let w = group.generate_private_key(); // No need for BigInt RNG with secp256k1 let s1 = p1.extract_secret_share(&distribute_shares_box, &p1.privatekey, &w).unwrap(); // Reconstruction - same method names let share_boxs = [s1, s2, s3]; let r1 = p1.reconstruct(&share_boxs, &distribute_shares_box).unwrap(); ``` **secp256k1 的主要区别:** - 元素是 EC 点 (`k256::AffinePoint`) 而不是 `BigInt` - 标量是 `k256::Scalar` (32 字节) 而不是 `BigInt` - 方法名与 MODP 相同(无需后缀) - 私钥通过 `group.generate_private_key()` 生成,而不是手动 BigInt RNG - `Scalar::from_repr` 期望大端字节表示 #### Ristretto255 用法 Ristretto255 是建立在 Curve25519 (Ed25519) 之上的素数阶群组。它通过构造素数阶商群解决了 Ed25519 的辅因子问题,使其非常适合 PVSS 等密码学协议。 ``` use mpvss_rs::groups::Ristretto255Group; use mpvss_rs::Participant; use mpvss_rs::group::Group; // Import Group trait for method access let secret_message = String::from("Hello MPVSS (Ristretto255)."); // Create the group (returns Arc) let group = Ristretto255Group::new(); // Create dealer and participants with the group let mut dealer = Participant::with_arc(group.clone()); dealer.initialize(); let mut p1 = Participant::with_arc(Ristretto255Group::new()); let mut p2 = Participant::with_arc(Ristretto255Group::new()); let mut p3 = Participant::with_arc(Ristretto255Group::new()); p1.initialize(); p2.initialize(); p3.initialize(); // Distribution - same method names as MODP and secp256k1 let distribute_shares_box = dealer.distribute_secret( &string_to_secret(&secret_message), &vec![p1.publickey.clone(), p2.publickey.clone(), p3.publickey.clone()], 3, ); // Verification - same method names assert_eq!(p1.verify_distribution_shares(&distribute_shares_box), true); // Share extraction let w = group.generate_private_key(); // No need for BigInt RNG let s1 = p1.extract_secret_share(&distribute_shares_box, &p1.privatekey, &w).unwrap(); // Reconstruction - same method names let share_boxs = [s1, s2, s3]; let r1 = p1.reconstruct(&share_boxs, &distribute_shares_box).unwrap(); ``` **Ristretto255 的主要区别:** - 元素是 Ristretto 点 (`curve25519_dalek::RistrettoPoint`) - 32 字节压缩编码 - 标量是 `curve25519_dalek::Scalar` (32 字节,小端序) - 素数阶群组 (cofactor = 1),消除了小子群攻击的隐患 - 方法名与其他群组相同(统一 API) - 私钥通过 `group.generate_private_key()` 生成 - 使用 SHA-512 进行哈希到标量(更宽的输出以获得更好的均匀性) ## 相关参考资料: - Berry Schoenmakers. [A Simple Publicly Verifiable Secret Sharing Scheme and its Application to Electronic Voting](https://www.win.tue.nl/~berry/papers/crypto99.pdf) - Adi Shamir. [How to share a secret](http://users.cms.caltech.edu/~vidick/teaching/101_crypto/Shamir1979.pdf) - Tal Rabin. [Verifiable Secret Sharing and Multiparty Protocols with Honest Majority](https://www.cs.umd.edu/users/gasarch/TOPICS/secretsharing/rabinVSS.pdf) - Markus Stadler. [Publicly Verifiable Secret Sharing](https://link.springer.com/content/pdf/10.1007%2F3-540-68339-9_17.pdf) - bitcoinwiki-org. [Publicly Verifiable Secret Sharing](https://en.bitcoinwiki.org/wiki/Publicly_Verifiable_Secret_Sharing) ## 非相关参考资料 因为本项目中的多项式承诺不是 Pedersen 承诺,且 DLEQ 仅具有计算安全性,而非信息论安全性。 - crypto-stackexchange. [What is a Pedersen commitment?](https://crypto.stackexchange.com/questions/64437/what-is-a-pedersen-commitment) - Torben Pryds Pedersen. [Non-Interactive and Information-Theoretic Secure Verifiable Secret Sharing](https://link.springer.com/content/pdf/10.1007%2F3-540-46766-1_9.pdf) - Chunming Tang. Dingyi Pei. [Non-Interactive and Information-Theoretic Secure Publicly Verifiable Secret Sharing](https://eprint.iacr.org/2004/201.pdf) ## 许可证 采用双重许可以与 Rust 项目兼容。 根据 Apache 许可证 2.0 版 [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) 或 MIT 许可证 [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT) 授权,您可任选其一。除非根据这些条款,否则不得复制、修改或分发此文件。
标签:Crates.io, CVE, meg, ProjectDiscovery, PVSS, Rust, SamuraiWTF, Web3, 信息安全, 公开可验证秘密共享, 分布式系统, 加密库, 区块链基础设施, 可视化界面, 响应大小分析, 密码学, 手动系统调用, 抗量子计算, 数字签名, 数据保护, 秘密共享, 网络流量审计, 通知系统, 门限密码学, 零知识证明, 非交互式零知识证明