#secret-sharing #shamir-secret-sharing #secret #sharing #verifiable

vsss-rs-std

用于分割、合并和验证秘密份额的可验证秘密共享方案

5 个版本

3.0.0-pre42023年3月20日
3.0.0-pre32023年3月14日
3.0.0-pre22023年3月13日
3.0.0-pre02023年3月10日

#1833 in 密码学

Download history 12/week @ 2024-03-28 6/week @ 2024-04-04 37/week @ 2024-04-18 7/week @ 2024-04-25

57 monthly downloads

Apache-2.0 OR MIT

95KB
2K SLoC

可验证秘密共享方案

Crate Docs Apache 2.0 Build status

当可用 Rust 标准库时,此 crate 提供各种密码学可验证秘密共享方案。

此 crate 已从 vsss-rs 分离,以便两个模式可以包含在同一项目中。

  • 此实现尚未经过审查或审计。使用风险自担。
  • 此实现针对 Rust 1.51 或更高版本。
  • 此实现不需要 Rust 标准库。
  • 除非明确说明,所有操作均为常数时间。

注意:如果从版本 2 升级

标准模式已拆分为 vsss-rs-std,以便在同一项目中包含两者。此外,接口已重新设计,以相互兼容以及与序列化兼容。

文档

可验证秘密共享方案用于将秘密分割成多个份额,并在不同实体之间分发,同时具有验证份额是否正确以及属于特定集合的能力。此 crate 包括不支持验证但更多是其他方案构建块的 Shamir 秘密共享方案。

此 crate 支持 Feldman 和 Pedersen 可验证秘密共享方案。

Feldman 和 Pedersen 在许多方面相似。很难描述何时使用一个而不是另一个。事实上,两者都用于 分布式密钥生成

Feldman 揭示了验证者的公共值,而 Pedersen 的则隐藏了它。

Feldman 和 Pedersen 在分割秘密方面与 Shamir 不同。将份额合并回原始秘密的方法对所有方法都相同,并且每个方案都提供方便。

此 crate 与 no-std 兼容,并使用 const generics 来指定大小。

此 crate 支持 255 个请求的最大份额数。任何更高都相当荒谬,但如果存在此类用例,请告诉我。

股份表示为字节数组。根据使用情况,股份可以表示有限域或群。

在指定股份大小时,使用字段大小(以字节为单位)+ 1 作为标识符。

P-256

使用Shamir分割P-256秘密

use vsss_rs::Shamir;
use ff::PrimeField;
use p256::{NonZeroScalar, Scalar, SecretKey};
use rand::rngs::OsRng;

fn main() {
    let mut osrng = OsRng::default();
    let sk = SecretKey::random(&mut osrng);
    let nzs = sk.to_secret_scalar();
    // 32 for field size, 1 for identifier = 33
    let res = Shamir::<2, 3>::split_secret::<Scalar, OsRng, 33>(*nzs.as_ref(), &mut osrng);
    assert!(res.is_ok());
    let shares = res.unwrap();
    let res = Shamir::<2, 3>::combine_shares::<Scalar, 33>(&shares);
    assert!(res.is_ok());
    let scalar = res.unwrap();
    let nzs_dup =  NonZeroScalar::from_repr(scalar.to_repr()).unwrap();
    let sk_dup = SecretKey::from(nzs_dup);
    assert_eq!(sk_dup.to_bytes(), sk.to_bytes());
}

Secp256k1

使用Shamir分割k256秘密

use vsss_rs::Shamir;
use ff::PrimeField;
use k256::{NonZeroScalar, Scalar, SecretKey};
use rand::rngs::OsRng;

fn main() {
    let mut osrng = OsRng::default();
    let sk = SecretKey::random(&mut osrng);
    let nzs = sk.to_secret_scalar();
    let res = Shamir::<2, 3>::split_secret::<Scalar, OsRng, 33>(*nzs.as_ref(), &mut osrng);
    assert!(res.is_ok());
    let shares = res.unwrap();
    let res = Shamir::<2, 3>::combine_shares::<Scalar, 33>(&shares);
    assert!(res.is_ok());
    let scalar = res.unwrap();
    let nzs_dup = NonZeroScalar::from_repr(scalar.to_repr()).unwrap();
    let sk_dup = SecretKey::from(nzs_dup);
    assert_eq!(sk_dup.to_bytes(), sk.to_bytes());
}

BLS12-381

Feldman或Pedersen在验证时返回额外信息

use vsss_rs::Feldman;
use bls12_381_plus::{Scalar, G1Projective};
use ff::Field;
use rand::rngs::OsRng;

fn main() {
    let mut rng = OsRng::default();
    let secret = Scalar::random(&mut rng);
    let res = Feldman::<2, 3>::split_secret::<Scalar, G1Projective, OsRng, 33>(secret, None, &mut rng);
    assert!(res.is_ok());
    let (shares, verifier) = res.unwrap();
    for s in &shares {
        assert!(verifier.verify(s));
    }
    let res = Feldman::<2, 3>::combine_shares::<Scalar, 33>(&shares);
    assert!(res.is_ok());
    let secret_1 = res.unwrap();
    assert_eq!(secret, secret_1);
}

Curve25519

Curve25519不是一个素域,但此crate默认支持它,使用features=["curve25519"],这默认启用。此功能封装了curve25519-dalek库,以便与Shamir、Feldman和Pedersen一起使用。

这是一个使用Ed25519和x25519的示例

use curve25519_dalek::scalar::Scalar;
use ed25519_dalek::SecretKey;
use vsss_rs::{Shamir, WrappedScalar};
use rand::rngs::OsRng;
use x25519_dalek::StaticSecret;

fn main() {
    let mut osrng = rand::rngs::OsRng::default();
    let sc = Scalar::random(&mut osrng);
    let sk1 = StaticSecret::from(sc.to_bytes());
    let ske1 = SecretKey::from_bytes(&sc.to_bytes()).unwrap();
    let res = Shamir::<2, 3>::split_secret::<WrappedScalar, OsRng, 33>(sc.into(), &mut osrng);
    assert!(res.is_ok());
    let shares = res.unwrap();
    let res = Shamir::<2, 3>::combine_shares::<WrappedScalar, 33>(&shares);
    assert!(res.is_ok());
    let scalar = res.unwrap();
    assert_eq!(scalar.0, sc);
    let sk2 = StaticSecret::from(scalar.0.to_bytes());
    let ske2 = SecretKey::from_bytes(&scalar.0.to_bytes()).unwrap();
    assert_eq!(sk2.to_bytes(), sk1.to_bytes());
    assert_eq!(ske1.to_bytes(), ske2.to_bytes());
}

使用Feldman和Pedersen VSSS时,可以使用RistrettoPointEdwardsPoint

许可

许可

根据您的选择,受以下任一许可的约束:

贡献

除非您明确表示,否则根据Apache-2.0许可定义的,您有意提交的任何贡献,用于包含在作品中,应按照上述方式许可,不附加任何其他条款或条件。

参考文献

  1. 如何共享秘密,Shamir,A. Nov,1979
  2. 非交互式可验证秘密共享的实用方案,Feldman,P. 1987
  3. 非交互式和信息论安全的可验证秘密共享,Pedersen,T. 1991

依赖项

~2.4–3.5MB
~73K SLoC