diff --git a/fastcrypto-vdf/benches/vdf.rs b/fastcrypto-vdf/benches/vdf.rs index e8de3d311..23f05f26b 100644 --- a/fastcrypto-vdf/benches/vdf.rs +++ b/fastcrypto-vdf/benches/vdf.rs @@ -82,13 +82,10 @@ fn verify(c: &mut Criterion) { } fn rsa_vdf(c: &mut Criterion) { - let modulus = GOOGLE_RSA_MODULUS_4096.clone(); + let modulus = Rc::new(GOOGLE_RSA_MODULUS_4096.clone()); let vdf = DefaultRSABasedVDF::new(modulus.clone(), 1000); - let input = RSAGroupElement { - value: BigUint::from(2u64), - modulus: Rc::new(modulus.clone()), - }; + let input = RSAGroupElement::new(BigUint::from(2u64), &modulus); println!("Modulus bits: {}", modulus.value.bits()); diff --git a/fastcrypto-vdf/src/groups/class_group/discriminant.rs b/fastcrypto-vdf/src/groups/class_group/discriminant.rs index 3311766a9..814baa405 100644 --- a/fastcrypto-vdf/src/groups/class_group/discriminant.rs +++ b/fastcrypto-vdf/src/groups/class_group/discriminant.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 use crate::groups::class_group::bigint_serde; -use crate::groups::Parameter; use crate::math::hash_prime; use crate::math::hash_prime::is_probable_prime; use fastcrypto::error::FastCryptoError::InvalidInput; @@ -19,8 +18,6 @@ use std::str::FromStr; #[derive(PartialEq, Eq, Debug, Clone, Serialize)] pub struct Discriminant(#[serde(with = "bigint_serde")] BigInt); -impl Parameter for Discriminant {} - lazy_static! { /// Fixed 3072 bit discriminant. Generated from the seed [1,2,3] using [Discriminant::from_seed]. // TODO: Generate this using a seed that we provably cannot influence. diff --git a/fastcrypto-vdf/src/groups/mod.rs b/fastcrypto-vdf/src/groups/mod.rs index 2acae89e3..aebac04e1 100644 --- a/fastcrypto-vdf/src/groups/mod.rs +++ b/fastcrypto-vdf/src/groups/mod.rs @@ -8,17 +8,13 @@ use fastcrypto::groups::Doubling; pub mod class_group; pub mod rsa_group; -/// This trait is implemented by types which can be used as parameters for a parameterized group. -/// See [ParameterizedGroupElement]. -pub trait Parameter: Eq + Sized {} - /// Trait implemented by elements of an additive group where the group is parameterized, for example /// by the modulus in case of the group being Z mod N or the discriminant in case of class groups. pub trait ParameterizedGroupElement: Sized + Clone + for<'a> Add<&'a Self, Output = Self> + Add + Eq + Doubling { /// The type of the parameter which uniquely defines this group. - type ParameterType: Parameter; + type ParameterType; /// Return an instance of the identity element in this group. fn zero(parameters: &Self::ParameterType) -> Self; diff --git a/fastcrypto-vdf/src/groups/rsa_group/mod.rs b/fastcrypto-vdf/src/groups/rsa_group/mod.rs index 832b93f3f..0ad6dfa07 100644 --- a/fastcrypto-vdf/src/groups/rsa_group/mod.rs +++ b/fastcrypto-vdf/src/groups/rsa_group/mod.rs @@ -6,7 +6,7 @@ use std::rc::Rc; use num_bigint::BigUint; use num_integer::Integer; -use num_traits::Zero; +use num_traits::One; use serde::{Deserialize, Serialize}; use fastcrypto::groups::Doubling; @@ -21,11 +21,21 @@ mod biguint_serde; pub mod modulus; pub(crate) mod multiplier; -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct RSAGroupElement { #[serde(with = "biguint_serde")] - pub value: BigUint, - pub modulus: Rc, + value: BigUint, + modulus: Rc, +} + +impl Clone for RSAGroupElement { + fn clone(&self) -> Self { + Self { + value: self.value.clone(), + // Ensure that we don't do a deep clone of the modulus. + modulus: Rc::clone(&self.modulus), + } + } } impl Add for RSAGroupElement { @@ -58,12 +68,12 @@ impl Doubling for RSAGroupElement { } impl ParameterizedGroupElement for RSAGroupElement { - type ParameterType = RSAModulus; + type ParameterType = Rc; fn zero(parameter: &Self::ParameterType) -> Self { Self { - value: BigUint::zero(), - modulus: Rc::new(parameter.clone()), + value: BigUint::one(), + modulus: Rc::clone(parameter), } } @@ -72,5 +82,69 @@ impl ParameterizedGroupElement for RSAGroupElement { } } +impl RSAGroupElement { + pub fn new(value: BigUint, modulus: &Rc) -> Self { + Self { + value, + modulus: Rc::clone(modulus), + } + } + + pub fn modulus(&self) -> &BigUint { + &self.modulus.value + } + + pub fn value(&self) -> &BigUint { + &self.value + } +} + #[cfg(test)] -mod tests {} +mod tests { + use crate::groups::rsa_group::modulus::{RSAModulus, GOOGLE_RSA_MODULUS_4096}; + use crate::groups::rsa_group::RSAGroupElement; + use crate::groups::ParameterizedGroupElement; + use fastcrypto::groups::Doubling; + use num_bigint::BigUint; + use std::ops::Add; + use std::rc::Rc; + + #[test] + fn test_group_ops() { + let modulus = Rc::new(GOOGLE_RSA_MODULUS_4096.clone()); + + let zero = RSAGroupElement::zero(&modulus); + let element = RSAGroupElement::new(BigUint::from(7u32), &modulus); + let sum = element.clone().add(&zero); + assert_eq!(&sum, &element); + + let double = element.double(); + let expected_double = element.clone().add(&element); + assert_eq!(&double, &expected_double); + } + + #[test] + fn test_clone() { + let modulus = Rc::new(GOOGLE_RSA_MODULUS_4096.clone()); + assert_eq!(Rc::strong_count(&modulus), 1); + let element = RSAGroupElement::new(BigUint::from(7u32), &modulus); + assert_eq!(Rc::strong_count(&modulus), 2); + { + let _cloned_element = element.clone(); + assert_eq!(Rc::strong_count(&modulus), 3); + } + assert_eq!(Rc::strong_count(&modulus), 2); + } + + #[test] + fn test_is_in_group() { + let modulus = Rc::new(GOOGLE_RSA_MODULUS_4096.clone()); + let element = RSAGroupElement::new(BigUint::from(7u32), &modulus); + assert!(element.is_in_group(&modulus)); + + let other_modulus = Rc::new(RSAModulus { + value: BigUint::from(15u32), + }); + assert!(!element.is_in_group(&other_modulus)); + } +} diff --git a/fastcrypto-vdf/src/groups/rsa_group/modulus.rs b/fastcrypto-vdf/src/groups/rsa_group/modulus.rs index da2fdf650..361785bc2 100644 --- a/fastcrypto-vdf/src/groups/rsa_group/modulus.rs +++ b/fastcrypto-vdf/src/groups/rsa_group/modulus.rs @@ -1,21 +1,19 @@ // Copyright (c) 2022, Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use crate::groups::rsa_group::biguint_serde; -use crate::groups::Parameter; use lazy_static::lazy_static; use num_bigint::BigUint; use num_traits::Num; use serde::{Deserialize, Serialize}; +use crate::groups::rsa_group::biguint_serde; + #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct RSAModulus { #[serde(with = "biguint_serde")] pub value: BigUint, } -impl Parameter for RSAModulus {} - lazy_static! { // Modulus from Google Certificate, GTS Root R1 (https://pki.goog/repository/). pub static ref GOOGLE_RSA_MODULUS_4096: RSAModulus = RSAModulus { diff --git a/fastcrypto-vdf/src/vdf/wesolowski/fiat_shamir.rs b/fastcrypto-vdf/src/vdf/wesolowski/fiat_shamir.rs index 910cab6a3..f31a7ec76 100644 --- a/fastcrypto-vdf/src/vdf/wesolowski/fiat_shamir.rs +++ b/fastcrypto-vdf/src/vdf/wesolowski/fiat_shamir.rs @@ -6,7 +6,7 @@ use serde::Serialize; use fastcrypto::groups::multiplier::ScalarMultiplier; -use crate::groups::{Parameter, ParameterizedGroupElement}; +use crate::groups::ParameterizedGroupElement; use crate::math::hash_prime::hash_prime; use crate::vdf::wesolowski::WesolowskisVDF; @@ -35,8 +35,8 @@ pub trait FiatShamir: Sized { /// See https://eprint.iacr.org/2023/691. pub struct StrongFiatShamir {} -impl + Serialize> - FiatShamir for StrongFiatShamir +impl + Serialize> FiatShamir + for StrongFiatShamir { fn compute_challenge>( vdf: &WesolowskisVDF, @@ -59,7 +59,7 @@ impl + } #[derive(Serialize)] -struct FiatShamirInput<'a, P: Parameter, G: ParameterizedGroupElement> { +struct FiatShamirInput<'a, P, G: ParameterizedGroupElement> { input: &'a G, output: &'a G, iterations: u64, diff --git a/fastcrypto-vdf/src/vdf/wesolowski/mod.rs b/fastcrypto-vdf/src/vdf/wesolowski/mod.rs index fb9d104ab..78a1b2154 100644 --- a/fastcrypto-vdf/src/vdf/wesolowski/mod.rs +++ b/fastcrypto-vdf/src/vdf/wesolowski/mod.rs @@ -215,18 +215,13 @@ mod tests { #[test] fn test_rsa_vdf() { - let modulus = RSAModulus { + let modulus = Rc::new(RSAModulus { value: BigUint::from_str("25195908475657893494027183240048398571429282126204032027777137836043662020707595556264018525880784406918290641249515082189298559149176184502808489120072844992687392807287776735971418347270261896375014971824691165077613379859095700097330459748808428401797429100642458691817195118746121515172654632282216869987549182422433637259085141865462043576798423387184774447920739934236584823824281198163815010674810451660377306056201619676256133844143603833904414952634432190114657544454178424020924616515723350778707749817125772467962926386356373289912154831438167899885040445364023527381951378636564391212010397122822120720357").unwrap(), - }; - - let modulus_pointer = Rc::new(modulus.clone()); + }); let vdf = DefaultRSABasedVDF::new(modulus.clone(), 1000); - let input = RSAGroupElement { - value: BigUint::from(2u64), - modulus: modulus_pointer, - }; + let input = RSAGroupElement::new(BigUint::from(2u64), &modulus); let (output, proof) = vdf.evaluate(&input).unwrap(); assert!(vdf.verify(&input, &output, &proof).is_ok());