diff --git a/polyfuzzy/src/fmd2_compact/mod.rs b/polyfuzzy/src/fmd2_compact/mod.rs index e949478..cc750e4 100644 --- a/polyfuzzy/src/fmd2_compact/mod.rs +++ b/polyfuzzy/src/fmd2_compact/mod.rs @@ -27,6 +27,30 @@ use crate::{ pub struct CompactSecretKey(#[cfg_attr(feature = "zeroize", zeroize)] Polynomial); impl CompactSecretKey { + /// Derive a [`CompactSecretKey`] from the given XOF stream. + pub fn derive_from_xof_stream(threshold: usize, mut squeeze_stream: S) -> Self + where + S: FnMut(&mut [u8; 32]), + { + let mut scratch_buffer = [0u8; 32]; + + let poly = Polynomial { + coeffs: core::iter::repeat_with(|| { + squeeze_stream(&mut scratch_buffer); + Scalar::from_bytes_mod_order(scratch_buffer) + }) + .take(threshold + 1) + .collect(), + }; + + #[cfg(feature = "zeroize")] + { + Zeroize::zeroize(&mut scratch_buffer); + } + + Self(poly) + } + /// Get the public key counterpart of this key /// with standard basepoint. pub fn master_public_key(&self) -> CompactPublicKey { diff --git a/polyfuzzy/src/fmd2_compact/polynomial.rs b/polyfuzzy/src/fmd2_compact/polynomial.rs index cb3e3ff..09f3f69 100644 --- a/polyfuzzy/src/fmd2_compact/polynomial.rs +++ b/polyfuzzy/src/fmd2_compact/polynomial.rs @@ -12,7 +12,7 @@ use zeroize::Zeroize; #[cfg_attr(feature = "zeroize", derive(Zeroize))] pub(crate) struct Polynomial { #[cfg_attr(feature = "zeroize", zeroize)] - coeffs: Vec, + pub(crate) coeffs: Vec, } /// A degree t polynomial encoded in the exponent of a Ristretto point diff --git a/polyfuzzy/src/fmd2_generic.rs b/polyfuzzy/src/fmd2_generic.rs index fa21b00..22aa905 100644 --- a/polyfuzzy/src/fmd2_generic.rs +++ b/polyfuzzy/src/fmd2_generic.rs @@ -64,6 +64,28 @@ impl CiphertextBits { pub struct FmdSecretKey(#[cfg_attr(feature = "zeroize", zeroize)] pub(crate) Vec); impl FmdSecretKey { + /// Derive an [`FmdSecretKey`] from the given XOF stream. + pub fn derive_from_xof_stream(gamma: usize, mut squeeze_stream: S) -> Self + where + S: FnMut(&mut [u8; 32]), + { + let mut scratch_buffer = [0u8; 32]; + + let keys = core::iter::repeat_with(|| { + squeeze_stream(&mut scratch_buffer); + Scalar::from_bytes_mod_order(scratch_buffer) + }) + .take(gamma) + .collect(); + + #[cfg(feature = "zeroize")] + { + Zeroize::zeroize(&mut scratch_buffer); + } + + Self(keys) + } + pub(crate) fn generate_keys(gamma: usize, rng: &mut R) -> Self { let keys = (0..gamma).map(|_| Scalar::random(rng)).collect();