Skip to main content

Crate vsss_rs

Crate vsss_rs 

Source
Expand description

Verifiable secret sharing schemes are used to split secrets into multiple shares and distribute them among different entities while providing the ability to verify that the shares are correct and belong to a specific set. This crate includes Shamir’s secret sharing scheme, which does not support verification but serves as a building block for the other schemes.

This crate supports Feldman and Pedersen verifiable secret sharing schemes.

Feldman and Pedersen are similar in many ways. It’s hard to describe when to use one over the other. Indeed, both are used in GennaroDKG.

Feldman reveals the public value of the verifier, whereas Pedersen hides it.

Feldman and Pedersen are different from Shamir when splitting the secret. Combining shares back into the original secret is identical across all methods and is available for each scheme for convenience.

This crate is no_std compatible and uses const generics to specify sizes.

Most applications need no more than 255 shares. That said, this crate does not impose that limit: any number can be requested because identifiers can be any size.

Shares are represented as ShareElements. A share element can use any suitable representation, but finite fields and groups are the most common, depending on the use case. In the simplest case, the share identifier is the x-coordinate, and the actual share value is the y-coordinate. However, anything can be used as the identifier as long as it implements the ShareIdentifier trait.

Feldman and Pedersen use the ShareVerifier trait to verify shares.

In version 5, many of the required generics were removed and replaced with associated types. This simplified the API, made it easier to use, and reduced the amount of necessary code.

To split a P-256 secret using Shamir:

#[cfg(any(feature = "alloc", feature = "std"))]
{
use vsss_rs::{*, shamir};
use elliptic_curve::{Generate, ff::PrimeField};
use p256::{NonZeroScalar, Scalar, SecretKey};
use rand::{rngs::StdRng, SeedableRng};

type P256Share = DefaultShare<IdentifierPrimeField<Scalar>, IdentifierPrimeField<Scalar>>;

let mut osrng = StdRng::from_seed([1u8; 32]);
let sk = SecretKey::generate_from_rng(&mut osrng);
let nzs = sk.to_nonzero_scalar();
let shared_secret = IdentifierPrimeField(*nzs.as_ref());
let res = shamir::split_secret::<P256Share>(2, 3, &shared_secret, &mut osrng);
assert!(res.is_ok());
let shares = res.unwrap();
let res = shares.combine();
assert!(res.is_ok());
let scalar = res.unwrap();
let nzs_dup =  NonZeroScalar::from_repr(scalar.0.to_repr()).unwrap();
let sk_dup = SecretKey::from(nzs_dup);
assert_eq!(sk_dup.to_bytes(), sk.to_bytes());
}

To split a K-256 secret using Shamir:

#[cfg(any(feature = "alloc", feature = "std"))]
{
use vsss_rs::{*, shamir};
use elliptic_curve::{Generate, ff::PrimeField};
use k256::{NonZeroScalar, Scalar, ProjectivePoint, SecretKey};
use rand::{rngs::StdRng, SeedableRng};

type K256Share = DefaultShare<IdentifierPrimeField<Scalar>, IdentifierPrimeField<Scalar>>;

let mut osrng = StdRng::from_seed([2u8; 32]);
let sk = SecretKey::generate_from_rng(&mut osrng);
let secret = IdentifierPrimeField(*sk.to_nonzero_scalar());
let res = shamir::split_secret::<K256Share>(2, 3, &secret, &mut osrng);
assert!(res.is_ok());
let shares = res.unwrap();
let res = shares.combine();
assert!(res.is_ok());
let scalar = res.unwrap();
let nzs_dup = NonZeroScalar::from_repr(scalar.0.to_repr()).unwrap();
let sk_dup = SecretKey::from(nzs_dup);
assert_eq!(sk_dup.to_bytes(), sk.to_bytes());
}

Feldman and Pedersen return extra information for verification using their respective verifiers.

#[cfg(any(feature = "alloc", feature = "std"))]
{
use vsss_rs::{*, feldman};
use k256::{ProjectivePoint, Scalar};
use elliptic_curve::ff::Field;
use rand::{rngs::StdRng, SeedableRng};

type K256Share = DefaultShare<IdentifierPrimeField<Scalar>, IdentifierPrimeField<Scalar>>;
type K256ShareVerifier = ShareVerifierGroup<ProjectivePoint>;

let mut rng = StdRng::from_seed([3u8; 32]);
let secret = IdentifierPrimeField(Scalar::random(&mut rng));
let res = feldman::split_secret::<K256Share, K256ShareVerifier>(2, 3, &secret, None, &mut rng);
assert!(res.is_ok());
let (shares, verifier) = res.unwrap();
for s in &shares {
    assert!(verifier.verify_share(s).is_ok());
}
let res = shares.combine();
assert!(res.is_ok());
let secret_1 = res.unwrap();
assert_eq!(secret, secret_1);
}

Curve25519-dalek 5.0.0 implements the native ff and group traits, so its scalar and group types can be used with Shamir, Feldman, and Pedersen.

Here is an example using Ed25519 and X25519:

#[cfg(any(feature = "alloc", feature = "std"))]
{
use curve25519_dalek::scalar::Scalar;
use rand::{RngExt, SeedableRng, rngs::StdRng};
use ed25519_dalek::SigningKey;
use vsss_rs::*;
use x25519_dalek::StaticSecret;

type Ed25519Share = DefaultShare<IdentifierPrimeField<Scalar>, IdentifierPrimeField<Scalar>>;

let mut osrng = StdRng::from_seed([4u8; 32]);
let sc = Scalar::hash_from_bytes::<sha2::Sha512>(&osrng.random::<[u8; 32]>());
let sk1 = StaticSecret::from(sc.to_bytes());
let ske1 = SigningKey::from_bytes(&sc.to_bytes());
let secret = IdentifierPrimeField(sc);
let res = shamir::split_secret::<Ed25519Share>(2, 3, &secret, &mut osrng);
assert!(res.is_ok());
let shares = res.unwrap();
let res = shares.combine();
assert!(res.is_ok());
let scalar = res.unwrap();
assert_eq!(scalar.0, sc);
let sk2 = StaticSecret::from(scalar.0.to_bytes());
let ske2 = SigningKey::from_bytes(&scalar.0.to_bytes());
assert_eq!(sk2.to_bytes(), sk1.to_bytes());
assert_eq!(ske1.to_bytes(), ske2.to_bytes());
}

Re-exports§

pub use feldman::Feldman;
pub use pedersen::Pedersen;
pub use pedersen::PedersenResult;
pub use shamir::Shamir;
pub use pedersen::StdPedersenResult;alloc or std
pub use elliptic_curve;curve
pub use subtle;

Modules§

boxed_uintbigint and (alloc or std)
Share element and identifier implementations using BoxedUint from crypto-bigint.
feldman
Feldman’s verifiable secret sharing scheme. See https://www.cs.umd.edu/~gasarch/TOPICS/secretsharing/feldmanVSS.pdf.
macros
Macros for creating VSSS implementations
pedersen
Pedersen’s verifiable secret sharing scheme. See https://www.cs.cornell.edu/courses/cs754/2001fa/129.PDF.
shamir
Secret splitting for Shamir’s secret sharing scheme and combination methods for field and group elements.
uintbigint
Share element and identifier implementations using Uint<LIMBS> from crypto-bigint.

Macros§

vsss_fixed_array_impl
Implements all the VSSS traits for a fixed array.

Structs§

ArrayFeldmanVerifierSet
A wrapper around a fixed-size array of verifiers. Allows for convenient type aliasing.
ArrayPedersenVerifierSet
A wrapper around an array of verifiers. Allows for convenient type aliasing.
DefaultShare
A default share implementation providing named fields for the identifier and value.
GenericArrayFeldmanVerifierSet
A wrapper around a generic array of verifiers. Allows for convenient type aliasing.
GenericArrayPedersenVerifierSet
A wrapper around a generic array of verifiers. Allows for convenient type aliasing.
Gf16
Represents the finite field GF(2^4) with 16 elements. Elements are stored in the lower nibble of a u8 (values 0x00..=0x0F). Uses the irreducible polynomial x^4 + x + 1 for multiplication.
Gf256
Represents the finite field GF(2^8) with 256 elements.
HybridArrayFeldmanVerifierSet
A wrapper around a hybrid array of verifiers. Allows for convenient type aliasing.
HybridArrayPedersenVerifierSet
A wrapper around a hybrid array of verifiers. Allows for convenient type aliasing.
IdentifierBigUintserde
A share identifier represented as a big unsigned number
IdentifierBoxedUintbigint and (alloc or std)
A share identifier represented as a heap-allocated unsigned integer with a fixed bit precision.
IdentifierConstMontyResiduebigint
A share identifier represented as a residue in Montgomery form modulo a constant modulus (crypto-bigint 0.7 ConstMontyForm).
IdentifierGf16
Represents an identifier in the Galois Field GF(2^4).
IdentifierGf256
Represents an identifier in the Galois Field GF(2^8).
IdentifierMontyResiduebigint
A share identifier represented as a residue in Montgomery form modulo a modulus chosen at runtime (crypto-bigint 0.7 FixedMontyForm).
IdentifierPrimeFieldcurve
A share identifier represented as a prime field element.
IdentifierPrimitiveprimitive
A share identifier represented as a primitive integer.
IdentifierResiduebigint
A share identifier represented as a residue modulo a modulus known at compile time.
ParticipantIdGeneratorCollection
A collection of participant number generators
Saturatingbigint
Provides intentionally saturating arithmetic on T.
StdVsssalloc or std
Standard verifiable secret sharing scheme.
ValueGroupcurve
A share element represented as a group element.
VecFeldmanVerifierSetalloc or std
A wrapper around a Vec of verifiers. Allows for convenient type aliasing.
VecPedersenVerifierSetalloc or std
A wrapper around a Vec of verifiers. Allows for convenient type aliasing.

Enums§

Error
Errors during secret sharing
ParticipantIdGenerator
The types of participant number generators.

Traits§

CtIsNotZero
A trait for indicating in constant time whether a value is nonzero.
CtIsZero
A trait for indicating in constant time whether a value is zero.
FeldmanVerifierSet
Objects that represent the ability to verify Shamir shares using Feldman verifiers.
FixedArray
A trait for converting a type to and from a fixed-size array.
PedersenVerifierSet
Objects that represent the ability to verify Shamir shares using Pedersen verifiers.
Polynomial
The polynomial used for generating the shares
Primitiveprimitive
An extension trait for primitive integers that are used as share identifiers.
PrimitiveZeroizeprimitive and zeroize
Placeholder for conditionally compiling in zeroize::DefaultIsZeroes.
ReadableShareSet
Represents a readable data store for secret shares
Share
A share.
ShareElement
A value used to represent a share element for secret shares. A share element can either be the share identifier or the share value.
ShareElementInner
A share element inner type for secret sharing schemes.
ShareIdentifier
A share identifier for secret sharing schemes.
ShareIdentifierInner
A share identifier inner type for secret sharing schemes.
ShareVerifier
Objects that represent the ability to verify Shamir shares.
WriteableShareSet
Represents a data store for secret shares

Functions§

combine_iteralloc or std
Combine an iterator of owned shares into a secret.
combine_iter_in_placealloc or std
Combine an iterator of owned shares into a secret, writing into out.
combine_streamstream
Combine exactly share_count shares from an asynchronous stream into a secret.
combine_stream_in_placestream
Combine exactly share_count shares from an asynchronous stream, writing into out.
validate_share_set
Validate that a share set has enough shares, non-zero identifiers, and no duplicate identifiers.

Type Aliases§

GroupSharecurve
A share whose identifier is a group scalar and whose value is a group element.
IdentifierI8primitive
A share identifier represented as i8.
IdentifierI16primitive
A share identifier represented as i16.
IdentifierI32primitive
A share identifier represented as i32.
IdentifierI64primitive
A share identifier represented as i64.
IdentifierI12864-bit and primitive
A share identifier represented as i128.
IdentifierIsizeprimitive
A share identifier represented as isize.
IdentifierU8primitive
A share identifier represented as u8.
IdentifierU16primitive
A share identifier represented as u16.
IdentifierU32primitive
A share identifier represented as u32.
IdentifierU64primitive
A share identifier represented as u64.
IdentifierU12864-bit and primitive
A share identifier represented as u128.
IdentifierUsizeprimitive
A share identifier represented as usize.
ParticipantIdGeneratorTypeDeprecated
Backward-compatible alias for ParticipantIdGenerator.
PrimeFieldSharecurve
A share whose identifier and value are elements of the same prime field.
ShareVerifierGroupcurve
A share verifier group element.
StdFeldmanalloc or std
Standard Feldman verifiable secret sharing scheme.
StdPedersenalloc or std
Standard Pedersen verifiable secret sharing scheme.
StdShamiralloc or std
Standard Shamir secret sharing scheme.
ValueBoxedUintbigint and (alloc or std)
A share value represented as BoxedUint.
ValueConstMontyResiduebigint
A share value represented as a ConstMontyForm<MOD, LIMBS>.
ValueI8primitive
A share value represented as i8.
ValueI16primitive
A share value represented as i16.
ValueI32primitive
A share value represented as i32.
ValueI64primitive
A share value represented as i64.
ValueI12864-bit and primitive
A share value represented as i128.
ValueIsizeprimitive
A share value represented as isize.
ValueMontyResiduebigint
A share value represented as a FixedMontyForm<LIMBS> (runtime modulus).
ValuePrimeFieldcurve
A share value represented as a PrimeField.
ValueResiduebigint
A share value represented as a Residue<MOD, LIMBS>.
ValueU8primitive
A share value represented as u8.
ValueU16primitive
A share value represented as u16.
ValueU32primitive
A share value represented as u32.
ValueU64primitive
A share value represented as u64.
ValueU12864-bit and primitive
A share value represented as u128.
ValueUsizeprimitive
A share value represented as usize.
VsssResult
Results returned by this crate