Skip to content

Commit

Permalink
Optimize verification
Browse files Browse the repository at this point in the history
  • Loading branch information
jonas-lj committed Oct 7, 2024
1 parent 8779439 commit c5a71d3
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 35 deletions.
39 changes: 18 additions & 21 deletions fastcrypto-vdf/src/math/parameterized_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,28 @@ pub trait ParameterizedGroupElement:

/// Returns true if this is an element of the group defined by `parameter`.
fn is_in_group(&self, parameter: &Self::ParameterType) -> bool;
}

/// Compute self * scalar using a "Double-and-Add" algorithm for a positive scalar.
pub(crate) fn multiply<G: ParameterizedGroupElement>(
input: &G,
scalar: &BigUint,
parameter: &G::ParameterType,
) -> G {
(0..scalar.bits())
.rev()
.map(|i| scalar.bit(i))
.fold(G::zero(parameter), |acc, bit| {
let mut res = acc.double();
if bit {
res = res + input;
}
res
})
/// Compute self * scalar.
fn multiply(&self, scalar: &BigUint, parameter: &Self::ParameterType) -> Self {
// Generic double-and-add algorithm.
(0..scalar.bits())
.rev()
.map(|i| scalar.bit(i))
.fold(Self::zero(parameter), |acc, bit| {
let mut res = acc.double();
if bit {
res = res + self;
}
res
})
}
}

#[cfg(test)]
mod tests {
use crate::class_group::discriminant::Discriminant;
use crate::class_group::QuadraticForm;
use crate::math::parameterized_group::{multiply, ParameterizedGroupElement};
use crate::math::parameterized_group::ParameterizedGroupElement;
use num_bigint::BigUint;
use num_traits::{One, Zero};

Expand All @@ -55,12 +52,12 @@ mod tests {
// Edge cases
assert_eq!(
QuadraticForm::zero(&discriminant),
multiply(&input, &BigUint::zero(), &discriminant)
input.multiply(&BigUint::zero(), &discriminant)
);
assert_eq!(input, multiply(&input, &BigUint::one(), &discriminant));
assert_eq!(input, input.multiply(&BigUint::one(), &discriminant));

let exponent = 12345u64;
let output = multiply(&input, &BigUint::from(exponent), &discriminant);
let output = input.multiply(&BigUint::from(exponent), &discriminant);

// Check alignment with repeated addition.
let mut expected_output = input.clone();
Expand Down
18 changes: 13 additions & 5 deletions fastcrypto-vdf/src/rsa_group/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use num_traits::One;
use rand::SeedableRng;
use rand_chacha::ChaCha20Rng;
use serde::Serialize;
use std::ops::{Add, Mul, SubAssign};
use std::ops::{Add, Mul};

pub mod modulus;

Expand Down Expand Up @@ -65,12 +65,20 @@ impl Doubling for RSAGroupElement<'_> {
impl<'a> ParameterizedGroupElement for RSAGroupElement<'a> {
type ParameterType = &'a RSAModulus;

fn zero(parameter: &Self::ParameterType) -> Self {
Self::new(BigUint::one(), parameter)
fn zero(modulus: &Self::ParameterType) -> Self {
Self::new(BigUint::one(), modulus)
}

fn is_in_group(&self, parameter: &Self::ParameterType) -> bool {
&self.modulus == parameter
fn is_in_group(&self, modulus: &Self::ParameterType) -> bool {
&self.modulus == modulus
}

fn multiply(&self, scalar: &BigUint, modulus: &Self::ParameterType) -> Self {
let value = self.value.modpow(scalar, &modulus.value);
Self {
value: self.modulus.ensure_in_subgroup(value),
modulus,
}
}
}

Expand Down
17 changes: 14 additions & 3 deletions fastcrypto-vdf/src/rsa_group/modulus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
use fastcrypto::error::FastCryptoError;
use num_bigint::BigUint;
use num_integer::Integer;
use num_traits::One;
use serde::Serialize;
use std::ops::Shr;
use std::ops::{Shl, Shr};
use std::str::FromStr;

#[derive(PartialEq, Eq, Debug, Serialize)]
Expand All @@ -15,6 +16,10 @@ pub struct RSAModulus {
/// Precomputed value of `modulus / 2` for faster reduction.
#[serde(skip)]
pub(super) half: BigUint,

/// Precomputed value of `2^{2 * log(modulus)}` for fast modular reduction.
#[serde(skip)]
pub(super) r: BigUint,
}

impl FromStr for RSAModulus {
Expand All @@ -34,7 +39,8 @@ impl From<BigUint> for RSAModulus {
/// responsibility to ensure that it is a valid RSA modulus.
fn from(value: BigUint) -> Self {
let half = (&value).shr(1);
Self { value, half }
let r = BigUint::one().shl(2 * value.bits()).div_floor(&value);
Self { value, half, r }
}
}

Expand All @@ -43,7 +49,12 @@ impl RSAModulus {
/// modulus, the result is negated. This is to ensure that the result is in the subgroup
/// <i>Z<sub>N</sub><sup>*</sup> / <±1></i>.
pub(super) fn reduce(&self, value: BigUint) -> BigUint {
let value = value.mod_floor(&self.value);
self.ensure_in_subgroup(value.mod_floor(&self.value))
}

/// Assuming that <i>value < N</i>, ensure that the given value is in the subgroup <i>Z<sub>N</sub><sup>*</sup> / <±1></i>.
/// Panics if the value is greater than or equal to <i>N</i>.
pub(super) fn ensure_in_subgroup(&self, value: BigUint) -> BigUint {
if value < self.half {
value
} else {
Expand Down
12 changes: 6 additions & 6 deletions fastcrypto-vdf/src/vdf/pietrzak.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use crate::math::parameterized_group::{multiply, ParameterizedGroupElement};
use crate::math::parameterized_group::ParameterizedGroupElement;
use crate::vdf::VDF;
use fastcrypto::error::FastCryptoError::{InvalidInput, InvalidProof};
use fastcrypto::error::FastCryptoResult;
Expand Down Expand Up @@ -87,8 +87,8 @@ where
let mu = x.clone().repeated_doubling(t_i);

let r = self.compute_challenge(&x, &y, &mu);
x = multiply(&x, &r, &self.group_parameter) + &mu;
y = multiply(&mu, &r, &self.group_parameter) + &y;
x = x.multiply(&r, &self.group_parameter) + &mu;
y = mu.multiply(&r, &self.group_parameter) + &y;

if t_i.is_odd() {
y = y.double();
Expand Down Expand Up @@ -119,8 +119,8 @@ where
}

let r = self.compute_challenge(&x, &y, mu);
x = multiply(&x, &r, &self.group_parameter) + mu;
y = multiply(mu, &r, &self.group_parameter) + &y;
x = x.multiply(&r, &self.group_parameter) + mu;
y = mu.multiply(&r, &self.group_parameter) + &y;
}

// In case the proof is shorter than the full proof, we need to compute the remaining powers.
Expand All @@ -142,7 +142,7 @@ fn check_parity_and_iterate(t: &mut u64) -> bool {
mod tests {
use crate::class_group::discriminant::Discriminant;
use crate::class_group::QuadraticForm;
use crate::rsa_group::modulus::test::{AMAZON_MODULUS_2048_REF, GOOGLE_MODULUS_4096_REF};
use crate::rsa_group::modulus::test::AMAZON_MODULUS_2048_REF;
use crate::rsa_group::RSAGroupElement;
use crate::vdf::pietrzak::PietrzaksVDF;
use crate::vdf::VDF;
Expand Down

0 comments on commit c5a71d3

Please sign in to comment.