vsss-rs 5.4.0

Verifiable Secret Sharing Schemes for splitting, combining and verifying secret shares
Documentation
use super::*;
use crate::*;
use core::{
    cmp::Ordering,
    fmt::{self, Display, Formatter},
    hash::{Hash, Hasher},
    ops::{Deref, DerefMut, Mul},
};
#[cfg(feature = "bigint")]
use elliptic_curve::{
    bigint::{self, ArrayEncoding, modular::constant_mod::ResidueParams},
    ops::Reduce,
};

use elliptic_curve::{Field, PrimeField, scalar::IsHigh};

/// A share value represented as a [`PrimeField`].
pub type ValuePrimeField<F> = IdentifierPrimeField<F>;

/// A share identifier represented as a prime field element.
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct IdentifierPrimeField<F: PrimeField>(
    #[cfg_attr(feature = "serde", serde(with = "elliptic_curve_tools::prime_field"))] pub F,
);

impl<F: PrimeField> Display for IdentifierPrimeField<F> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        for &b in self.0.to_repr().as_ref() {
            write!(f, "{:02x}", b)?;
        }
        Ok(())
    }
}

impl<F: PrimeField> Hash for IdentifierPrimeField<F> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.0.to_repr().as_ref().hash(state);
    }
}

#[allow(clippy::non_canonical_partial_ord_impl)]
impl<F: PrimeField + IsHigh> PartialOrd for IdentifierPrimeField<F> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        match (self.0.is_high().unwrap_u8(), other.0.is_high().unwrap_u8()) {
            (1, 1) => Some(other.0.to_repr().as_ref().cmp(self.0.to_repr().as_ref())),
            (0, 0) => Some(self.0.to_repr().as_ref().cmp(other.0.to_repr().as_ref())),
            (1, 0) => Some(Ordering::Less),
            (0, 1) => Some(Ordering::Greater),
            (_, _) => None,
        }
    }
}

impl<F: PrimeField + IsHigh> Ord for IdentifierPrimeField<F> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).expect("invalid share identifier")
    }
}

impl<F: PrimeField> Deref for IdentifierPrimeField<F> {
    type Target = F;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<F: PrimeField> DerefMut for IdentifierPrimeField<F> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl<F: PrimeField> AsRef<F> for IdentifierPrimeField<F> {
    fn as_ref(&self) -> &F {
        &self.0
    }
}

impl<F: PrimeField> AsMut<F> for IdentifierPrimeField<F> {
    fn as_mut(&mut self) -> &mut F {
        &mut self.0
    }
}

impl<F: PrimeField> From<F> for IdentifierPrimeField<F> {
    fn from(value: F) -> Self {
        Self(value)
    }
}

impl<F: PrimeField> From<&IdentifierPrimeField<F>> for IdentifierPrimeField<F> {
    fn from(value: &IdentifierPrimeField<F>) -> Self {
        *value
    }
}

#[cfg(feature = "primitive")]
impl<F: PrimeField, P: Primitive<BYTES>, const BYTES: usize> From<&IdentifierPrimitive<P, BYTES>>
    for IdentifierPrimeField<F>
{
    fn from(value: &IdentifierPrimitive<P, BYTES>) -> Self {
        #[cfg(target_pointer_width = "64")]
        {
            if BYTES * 8 <= 64 {
                Self(F::from(value.0.to_u64().expect("invalid share identifier")))
            } else {
                Self(F::from_u128(
                    value.0.to_u128().expect("invalid share identifier"),
                ))
            }
        }
        #[cfg(target_pointer_width = "32")]
        {
            Self(F::from(value.0.to_u64().expect("invalid share identifier")))
        }
    }
}

#[cfg(feature = "bigint")]
impl<F: PrimeField + Reduce<bigint::Uint<LIMBS>>, const LIMBS: usize>
    From<&uint5::IdentifierUint<LIMBS>> for IdentifierPrimeField<F>
where
    bigint::Uint<LIMBS>: ArrayEncoding,
{
    fn from(value: &uint5::IdentifierUint<LIMBS>) -> Self {
        if LIMBS * 8 != F::Repr::default().as_ref().len() {
            panic!(
                "cannot convert from IdentifierUint to IdentifierPrimeField with different limb size"
            );
        }
        Self(F::reduce(value.0.0))
    }
}

#[cfg(feature = "bigint")]
impl<F: PrimeField + Reduce<bigint::Uint<LIMBS>>, MOD: ResidueParams<LIMBS>, const LIMBS: usize>
    From<&IdentifierResidue<MOD, LIMBS>> for IdentifierPrimeField<F>
where
    bigint::Uint<LIMBS>: ArrayEncoding,
{
    fn from(value: &IdentifierResidue<MOD, LIMBS>) -> Self {
        let t = value.0.retrieve();
        Self(F::reduce(t))
    }
}

impl<F: PrimeField> Mul<&IdentifierPrimeField<F>> for IdentifierPrimeField<F> {
    type Output = IdentifierPrimeField<F>;

    fn mul(self, rhs: &IdentifierPrimeField<F>) -> Self::Output {
        Self(self.0 * rhs.0)
    }
}

#[cfg(feature = "primitive")]
impl<F: PrimeField, P: Primitive<BYTES>, const BYTES: usize> Mul<&IdentifierPrimitive<P, BYTES>>
    for IdentifierPrimeField<F>
{
    type Output = IdentifierPrimeField<F>;

    fn mul(self, rhs: &IdentifierPrimitive<P, BYTES>) -> Self::Output {
        let rhs = IdentifierPrimeField::<F>::from(rhs);
        Self(self.0 * rhs.0)
    }
}

#[cfg(feature = "bigint")]
impl<F: PrimeField + Reduce<bigint::Uint<LIMBS>>, const LIMBS: usize>
    Mul<&uint5::IdentifierUint<LIMBS>> for IdentifierPrimeField<F>
where
    bigint::Uint<LIMBS>: ArrayEncoding,
{
    type Output = IdentifierPrimeField<F>;

    fn mul(self, rhs: &uint5::IdentifierUint<LIMBS>) -> Self::Output {
        let rhs = IdentifierPrimeField::<F>::from(rhs);
        Self(self.0 * rhs.0)
    }
}

#[cfg(feature = "bigint")]
impl<F: PrimeField + Reduce<bigint::Uint<LIMBS>>, MOD: ResidueParams<LIMBS>, const LIMBS: usize>
    Mul<&IdentifierResidue<MOD, LIMBS>> for IdentifierPrimeField<F>
where
    bigint::Uint<LIMBS>: ArrayEncoding,
{
    type Output = IdentifierPrimeField<F>;

    fn mul(self, rhs: &IdentifierResidue<MOD, LIMBS>) -> Self::Output {
        let rhs = IdentifierPrimeField::<F>::from(rhs);
        Self(self.0 * rhs.0)
    }
}

#[cfg(feature = "bigint")]
impl<F: PrimeField + Reduce<bigint::Uint<LIMBS>>, const LIMBS: usize>
    From<&uint::IdentifierUint<LIMBS>> for IdentifierPrimeField<F>
where
    crypto_bigint::Uint<LIMBS>: crypto_bigint::Encoding,
{
    fn from(value: &uint::IdentifierUint<LIMBS>) -> Self {
        if LIMBS * 8 != F::Repr::default().as_ref().len() {
            panic!(
                "cannot convert from IdentifierUint to IdentifierPrimeField with different limb size"
            );
        }
        Self(F::reduce(bigint::Uint::from_words(value.0.to_words())))
    }
}

#[cfg(feature = "bigint")]
impl<F: PrimeField + Reduce<bigint::Uint<LIMBS>>, const LIMBS: usize>
    Mul<&uint::IdentifierUint<LIMBS>> for IdentifierPrimeField<F>
where
    crypto_bigint::Uint<LIMBS>: crypto_bigint::Encoding,
{
    type Output = IdentifierPrimeField<F>;

    fn mul(self, rhs: &uint::IdentifierUint<LIMBS>) -> Self::Output {
        let rhs = IdentifierPrimeField::<F>::from(rhs);
        Self(self.0 * rhs.0)
    }
}

#[cfg(feature = "bigint")]
impl<
    F: PrimeField + Reduce<bigint::Uint<LIMBS>>,
    MOD: crypto_bigint::modular::ConstMontyParams<LIMBS>,
    const LIMBS: usize,
> From<&IdentifierConstMontyResidue<MOD, LIMBS>> for IdentifierPrimeField<F>
where
    crypto_bigint::Uint<LIMBS>: crypto_bigint::Encoding,
{
    fn from(value: &IdentifierConstMontyResidue<MOD, LIMBS>) -> Self {
        let t = value.0.retrieve();
        Self(F::reduce(bigint::Uint::from_words(t.to_words())))
    }
}

#[cfg(feature = "bigint")]
impl<
    F: PrimeField + Reduce<bigint::Uint<LIMBS>>,
    MOD: crypto_bigint::modular::ConstMontyParams<LIMBS>,
    const LIMBS: usize,
> Mul<&IdentifierConstMontyResidue<MOD, LIMBS>> for IdentifierPrimeField<F>
where
    crypto_bigint::Uint<LIMBS>: crypto_bigint::Encoding,
{
    type Output = IdentifierPrimeField<F>;

    fn mul(self, rhs: &IdentifierConstMontyResidue<MOD, LIMBS>) -> Self::Output {
        let rhs = IdentifierPrimeField::<F>::from(rhs);
        Self(self.0 * rhs.0)
    }
}

#[cfg(feature = "zeroize")]
impl<F: PrimeField + zeroize::DefaultIsZeroes> zeroize::DefaultIsZeroes
    for IdentifierPrimeField<F>
{
}

impl<F: PrimeField> ShareElement for IdentifierPrimeField<F> {
    type Serialization = F::Repr;
    type Inner = F;

    fn random(rng: impl RngCore + CryptoRng) -> Self {
        Self(F::random(rng))
    }

    fn zero() -> Self {
        Self(<F as Field>::ZERO)
    }

    fn one() -> Self {
        Self(<F as Field>::ONE)
    }

    fn is_zero(&self) -> Choice {
        F::is_zero(self)
    }

    fn serialize(&self) -> Self::Serialization {
        self.to_repr()
    }

    fn deserialize(serialized: &Self::Serialization) -> VsssResult<Self> {
        Option::from(F::from_repr(*serialized).map(Self)).ok_or(Error::InvalidShareElement)
    }

    fn from_slice(vec: &[u8]) -> VsssResult<Self> {
        let mut repr = F::Repr::default();
        if vec.len() != repr.as_ref().len() {
            return Err(Error::InvalidShareElement);
        }
        repr.as_mut().copy_from_slice(vec);
        Option::from(F::from_repr(repr))
            .map(Self)
            .ok_or(Error::InvalidShareElement)
    }

    #[cfg(any(feature = "alloc", feature = "std"))]
    fn to_vec(&self) -> Vec<u8> {
        self.to_repr().as_ref().to_vec()
    }
}

impl<F: PrimeField> ShareIdentifier for IdentifierPrimeField<F> {
    fn inc(&mut self, increment: &Self) {
        self.0 += increment.0;
    }

    fn invert(&self) -> VsssResult<Self> {
        Option::from(self.0.invert())
            .map(Self)
            .ok_or(Error::InvalidShareElement)
    }
}

impl<F: PrimeField> IdentifierPrimeField<F> {
    /// Returns additive identity.
    pub const ZERO: Self = Self(F::ZERO);
    /// Returns multiplicative identity.
    pub const ONE: Self = Self(F::ONE);
}