diff --git a/polyfuzzy/src/fmd2.rs b/polyfuzzy/src/fmd2.rs index e6af927..9943649 100644 --- a/polyfuzzy/src/fmd2.rs +++ b/polyfuzzy/src/fmd2.rs @@ -90,7 +90,10 @@ impl Fmd2MultikeyScheme { impl FmdKeyGen for Fmd2MultikeyScheme { /// Generates as many subkeys as the γ parameter of `self`. - fn generate_keys(&self, rng: &mut R) -> (FmdSecretKey, FmdPublicKey) { + fn generate_keys( + &mut self, + rng: &mut R, + ) -> (FmdSecretKey, FmdPublicKey) { let gamma = self.gamma(); // Secret key. diff --git a/polyfuzzy/src/fmd2_compact/mod.rs b/polyfuzzy/src/fmd2_compact/mod.rs index 39e26fa..97b8b92 100644 --- a/polyfuzzy/src/fmd2_compact/mod.rs +++ b/polyfuzzy/src/fmd2_compact/mod.rs @@ -130,14 +130,18 @@ struct ExpandedKeyCache { } impl ExpandedKeyCache { - fn new(scheme: &MultiFmd2CompactScheme, pk: &CompactPublicKey) -> Self { + fn new(scheme: &mut MultiFmd2CompactScheme, pk: &CompactPublicKey) -> Self { Self { fingerprint: pk.fingerprint, randomized_key: scheme.expand_public_key(pk), } } - fn or_update(&mut self, scheme: &MultiFmd2CompactScheme, pk: &CompactPublicKey) -> &mut Self { + fn or_update( + &mut self, + scheme: &mut MultiFmd2CompactScheme, + pk: &CompactPublicKey, + ) -> &mut Self { if self.fingerprint.ct_ne(&pk.fingerprint).into() { self.fingerprint = pk.fingerprint; self.randomized_key = scheme.expand_public_key(pk); @@ -149,6 +153,8 @@ impl ExpandedKeyCache { /// The multi-key FMD scheme supporting key expansion and key randomization. #[derive(Debug, Clone, PartialEq, Eq)] pub struct MultiFmd2CompactScheme { + /// The gamma parameter + gamma: usize, /// The threshold parameter threshold: usize, ///the γ public scalars to derive keys from. @@ -161,28 +167,40 @@ pub struct MultiFmd2CompactScheme { impl MultiFmd2CompactScheme { /// Public scalars default to 1,...,γ in Z_q. - pub fn new(gamma: usize, threshold: usize) -> Self { - let mut public_scalars = Vec::new(); - let mut scalar = Scalar::ONE; - for _i in 0..gamma { - // Safely assume γ << q - public_scalars.push(scalar); - scalar += Scalar::ONE; - } + pub const fn new(gamma: usize, threshold: usize) -> Self { MultiFmd2CompactScheme { + gamma, threshold, - public_scalars, + public_scalars: Vec::new(), expanded_pk: None, - ciphertext_bits: CiphertextBits(Vec::with_capacity(gamma)), + ciphertext_bits: CiphertextBits(Vec::new()), + } + } + + fn init_public_scalars(&mut self) { + if !self.public_scalars.is_empty() { + return; + } + + let mut scalar = Scalar::ONE; + + for _i in 0..self.gamma { + // Safely assume γ << q + self.public_scalars.push(scalar); + scalar += Scalar::ONE; } } + + fn init_ciphertext_bits(&mut self) { + self.ciphertext_bits.0.reserve(self.gamma); + } } impl FmdKeyGen for MultiFmd2CompactScheme { /// Public keys generated have basepoint hardcoded to Ristretto basepoint. /// Thus, the master or original public key (as opposed to diversified keys) fn generate_keys( - &self, + &mut self, rng: &mut R, ) -> (CompactSecretKey, CompactPublicKey) { let degree = self.threshold; @@ -234,17 +252,21 @@ impl MultiFmdScheme for MultiFmd2CompactSchem detection_key: &crate::DetectionKey, flag_ciphers: &FlagCiphertexts, ) -> bool { + self.init_ciphertext_bits(); detection_key.detect(&mut self.ciphertext_bits, &flag_ciphers.0) } } impl KeyExpansion for MultiFmd2CompactScheme { fn expand_keypair( - &self, + &mut self, parent_sk: &CompactSecretKey, parent_pk: &CompactPublicKey, ) -> (FmdSecretKey, FmdPublicKey) { - let evaluations = parent_sk.0.evaluate(&self.public_scalars); + let evaluations = parent_sk.0.evaluate({ + self.init_public_scalars(); + &self.public_scalars + }); let encoded_evaluations = evaluations.encode(&parent_pk.polynomial.basepoint); ( @@ -253,15 +275,18 @@ impl KeyExpansion for MultiFmd ) } - fn expand_public_key(&self, parent_pk: &CompactPublicKey) -> FmdPublicKey { - let encoded_evaluations = parent_pk.polynomial.evaluate(&self.public_scalars); + fn expand_public_key(&mut self, parent_pk: &CompactPublicKey) -> FmdPublicKey { + let encoded_evaluations = parent_pk.polynomial.evaluate({ + self.init_public_scalars(); + &self.public_scalars + }); FmdPublicKey(encoded_evaluations) } } impl KeyRandomization for MultiFmd2CompactScheme { - fn randomize(&self, sk: &CompactSecretKey, tag: &[u8; 64]) -> CompactPublicKey { + fn randomize(&mut self, sk: &CompactSecretKey, tag: &[u8; 64]) -> CompactPublicKey { let encoded_polynomial = sk.0.encode_with_hashed_basepoint(tag); CompactPublicKey::from_poly(encoded_polynomial) @@ -324,7 +349,7 @@ mod tests { fn test_expand_is_correct() { let mut csprng = rand_core::OsRng; - let compact_multi_fmd2 = MultiFmd2CompactScheme::new(10, 3); + let mut compact_multi_fmd2 = MultiFmd2CompactScheme::new(10, 3); let (master_csk, master_cpk) = compact_multi_fmd2.generate_keys(&mut csprng); let (_fmd_sk, fmd_pk) = compact_multi_fmd2.expand_keypair(&master_csk, &master_cpk); @@ -338,7 +363,7 @@ mod tests { fn test_expand_and_randomize_are_compatible() { let mut csprng = rand_core::OsRng; - let compact_multi_fmd2 = MultiFmd2CompactScheme::new(10, 3); + let mut compact_multi_fmd2 = MultiFmd2CompactScheme::new(10, 3); let (master_csk, master_cpk) = compact_multi_fmd2.generate_keys(&mut csprng); // Randomize then expand. diff --git a/polyfuzzy/src/lib.rs b/polyfuzzy/src/lib.rs index ca9d532..1873ed5 100644 --- a/polyfuzzy/src/lib.rs +++ b/polyfuzzy/src/lib.rs @@ -37,14 +37,14 @@ pub trait MultiFmdScheme { /// /// Depending on implementations, the generated keypair can be compact. pub trait FmdKeyGen { - fn generate_keys(&self, rng: &mut R) -> (SK, PK); + fn generate_keys(&mut self, rng: &mut R) -> (SK, PK); } /// A trait to derive an FMD keypair ([FmdSecretKey],DPK) from a keypair (SK,PK). pub trait KeyExpansion: FmdKeyGen { - fn expand_keypair(&self, parent_sk: &SK, parent_pk: &PK) -> (FmdSecretKey, DPK); + fn expand_keypair(&mut self, parent_sk: &SK, parent_pk: &PK) -> (FmdSecretKey, DPK); - fn expand_public_key(&self, parent_pk: &PK) -> DPK; + fn expand_public_key(&mut self, parent_pk: &PK) -> DPK; } /// A trait to randomize public keys. @@ -67,5 +67,5 @@ pub trait KeyRandomization { /// The randomized public key is bound to the tag. Different tags yield /// different randomized public keys. /// The input tag _should_ be uniform (e.g. a hash digest). - fn randomize(&self, sk: &SK, tag: &[u8; 64]) -> PK; + fn randomize(&mut self, sk: &SK, tag: &[u8; 64]) -> PK; }