Skip to content

Commit

Permalink
refactor: make helper methods private
Browse files Browse the repository at this point in the history
  • Loading branch information
bobbinth committed Mar 18, 2024
1 parent cdb81df commit c8411da
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 72 deletions.
17 changes: 1 addition & 16 deletions src/dsa/rpo_falcon512/keys/mod.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,15 @@
use super::{
math::{FalconFelt, FastFft, Polynomial},
math::{FalconFelt, Polynomial},
ByteReader, ByteWriter, Deserializable, DeserializationError, Felt, Serializable, Signature,
Word, MODULUS,
};
use num::Complex;
use num_complex::Complex64;

mod public_key;
pub use public_key::{PubKeyPoly, PublicKey};

mod secret_key;
pub use secret_key::SecretKey;

// HELPER
// ================================================================================================

/// Computes the complex FFT of the secret key polynomials.
fn to_complex_fft(basis: &[Polynomial<i16>; 4]) -> [Polynomial<Complex<f64>>; 4] {
let [g, f, big_g, big_f] = basis.clone();
let g_fft = g.map(|cc| Complex64::new(*cc as f64, 0.0)).fft();
let minus_f_fft = f.map(|cc| -Complex64::new(*cc as f64, 0.0)).fft();
let big_g_fft = big_g.map(|cc| Complex64::new(*cc as f64, 0.0)).fft();
let minus_big_f_fft = big_f.map(|cc| -Complex64::new(*cc as f64, 0.0)).fft();
[g_fft, minus_f_fft, big_g_fft, minus_big_f_fft]
}

// TESTS
// ================================================================================================

Expand Down
71 changes: 44 additions & 27 deletions src/dsa/rpo_falcon512/keys/secret_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ use super::{
ByteReader, ByteWriter, Deserializable, DeserializationError, FalconError, Nonce,
Serializable, ShortLatticeBasis, Signature, Word, MODULUS, N, SIGMA, SIG_L2_BOUND,
},
to_complex_fft, PubKeyPoly, PublicKey,
PubKeyPoly, PublicKey,
};
use crate::dsa::rpo_falcon512::{hash_to_point::hash_to_point_rpo256, SIG_NONCE_LEN, SK_LEN};
use alloc::{string::ToString, vec::Vec};
use num::{Complex, Zero};
use rand::{thread_rng, Rng};

Check warning on line 16 in src/dsa/rpo_falcon512/keys/secret_key.rs

View workflow job for this annotation

GitHub Actions / test nightly on ubuntu with --no-default-features

unused import: `thread_rng`

Check warning on line 16 in src/dsa/rpo_falcon512/keys/secret_key.rs

View workflow job for this annotation

GitHub Actions / test stable on ubuntu with --no-default-features

unused import: `thread_rng`

use num_complex::Complex64;

// SECRET KEY
// ================================================================================================

Expand Down Expand Up @@ -76,17 +78,6 @@ impl SecretKey {
Self { secret_key: basis, tree }
}

/// Derives the public key corresponding to this secret key using h = g /f [mod ϕ][mod p].
pub fn compute_pub_key_poly(&self) -> PubKeyPoly {
let g: Polynomial<FalconFelt> = self.secret_key[0].clone().into();
let g_fft = g.fft();
let minus_f: Polynomial<FalconFelt> = self.secret_key[1].clone().into();
let f = -minus_f;
let f_fft = f.fft();
let h_fft = g_fft.hadamard_div(&f_fft);
h_fft.ifft().into()
}

// PUBLIC ACCESSORS
// --------------------------------------------------------------------------------------------

Expand All @@ -97,7 +88,6 @@ impl SecretKey {

/// Returns the public key corresponding to this secret key.
pub fn public_key(&self) -> PublicKey {
// TODO: memoize public key commitment as computing it requires quite a bit of hashing.
self.compute_pub_key_poly().into()
}

Expand Down Expand Up @@ -126,14 +116,28 @@ impl SecretKey {
Ok(Signature::new(nonce, s1, s2))
}

// HELPER METHODS
// --------------------------------------------------------------------------------------------

/// Derives the public key corresponding to this secret key using h = g /f [mod ϕ][mod p].
fn compute_pub_key_poly(&self) -> PubKeyPoly {
let g: Polynomial<FalconFelt> = self.secret_key[0].clone().into();
let g_fft = g.fft();
let minus_f: Polynomial<FalconFelt> = self.secret_key[1].clone().into();
let f = -minus_f;
let f_fft = f.fft();
let h_fft = g_fft.hadamard_div(&f_fft);
h_fft.ifft().into()
}

/// Signs a message polynomial with the secret key.
///
/// Takes a randomness generator implementing `Rng` and message polynomial representing `c`
/// the hash-to-point of the message to be signed. It outputs a signature `Signature`.
///
/// # Errors
/// Returns an error of signature generation fails.
pub fn sign_helper<R: Rng>(
fn sign_helper<R: Rng>(
&self,
c: Polynomial<FalconFelt>,
rng: &mut R,
Expand Down Expand Up @@ -196,16 +200,6 @@ impl SecretKey {
};
Ok(s)
}

/// Determines how many bits to use for each field element of a given polynomial of the secret
/// key during decoding.
fn field_element_width(polynomial_index: usize) -> usize {
if polynomial_index == 2 {
8
} else {
6
}
}
}

// SERIALIZATION / DESERIALIZATION
Expand Down Expand Up @@ -270,9 +264,9 @@ impl Deserializable for SecretKey {
));
}

let width_f = Self::field_element_width(0);
let width_g = Self::field_element_width(1);
let width_big_f = Self::field_element_width(2);
let width_f = field_element_width(0);
let width_g = field_element_width(1);
let width_big_f = field_element_width(2);

if byte_vector.len() != SK_LEN {
return Err(DeserializationError::InvalidValue("Invalid encoding length: Failed to decode as length is different from the one expected".to_string()));
Expand Down Expand Up @@ -308,3 +302,26 @@ impl Deserializable for SecretKey {
Ok(Self::from_short_lattice_basis(basis))
}
}

// HELPER FUNCTIONS
// ================================================================================================

/// Computes the complex FFT of the secret key polynomials.
fn to_complex_fft(basis: &[Polynomial<i16>; 4]) -> [Polynomial<Complex<f64>>; 4] {
let [g, f, big_g, big_f] = basis.clone();
let g_fft = g.map(|cc| Complex64::new(*cc as f64, 0.0)).fft();
let minus_f_fft = f.map(|cc| -Complex64::new(*cc as f64, 0.0)).fft();
let big_g_fft = big_g.map(|cc| Complex64::new(*cc as f64, 0.0)).fft();
let minus_big_f_fft = big_f.map(|cc| -Complex64::new(*cc as f64, 0.0)).fft();
[g_fft, minus_f_fft, big_g_fft, minus_big_f_fft]
}

/// Determines how many bits to use for each field element of a given polynomial of the secret
/// key during decoding.
fn field_element_width(polynomial_index: usize) -> usize {
if polynomial_index == 2 {
8
} else {
6
}
}
58 changes: 29 additions & 29 deletions src/dsa/rpo_falcon512/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,35 +87,7 @@ impl Signature {
let c = hash_to_point_rpo256(message, &self.nonce);
let s1 = self.s1.clone();
let s2 = self.s2.clone();
Self::verify_helper(c, s1, s2, pubkey_com)
}

/// Takes the hash-to-point polynomial `c` of a message and the signature polynomials over
/// the message `(s1, s2)` and returns `true` is the signature is a valid signature for
/// the given parameters, otherwise it returns `false`.
pub fn verify_helper(
c: Polynomial<FalconFelt>,
s1: SignaturePoly,
s2: SignaturePoly,
pubkey_com: Word,
) -> bool {
let s1_fft = s1.fft();
let s2_fft = s2.fft();
let c_fft = c.fft();

// h = s2^(-1) * (c - s1)
let h_fft = (c_fft - s1_fft).hadamard_div(&s2_fft);
let h = h_fft.ifft();

let length_squared_s1 = s1.norm_squared();
let length_squared_s2 = s2.norm_squared();
let length_squared = length_squared_s1 + length_squared_s2;
let is_short = length_squared < SIG_L2_BOUND;

let h: Polynomial<Felt> = h.into();
let h_digest: Word = Rpo256::hash_elements(&h.coefficients).into();

h_digest == pubkey_com && is_short
verify_helper(c, s1, s2, pubkey_com)
}
}

Expand Down Expand Up @@ -230,6 +202,34 @@ impl Deserializable for SignaturePoly {
// HELPER FUNCTIONS
// ================================================================================================

/// Takes the hash-to-point polynomial `c` of a message and the signature polynomials over
/// the message `(s1, s2)` and returns `true` is the signature is a valid signature for
/// the given parameters, otherwise it returns `false`.
fn verify_helper(
c: Polynomial<FalconFelt>,
s1: SignaturePoly,
s2: SignaturePoly,
pubkey_com: Word,
) -> bool {
let s1_fft = s1.fft();
let s2_fft = s2.fft();
let c_fft = c.fft();

// h = s2^(-1) * (c - s1)
let h_fft = (c_fft - s1_fft).hadamard_div(&s2_fft);
let h = h_fft.ifft();

let length_squared_s1 = s1.norm_squared();
let length_squared_s2 = s2.norm_squared();
let length_squared = length_squared_s1 + length_squared_s2;
let is_short = length_squared < SIG_L2_BOUND;

let h: Polynomial<Felt> = h.into();
let h_digest: Word = Rpo256::hash_elements(&h.coefficients).into();

h_digest == pubkey_com && is_short
}

/// Checks whether a set of coefficients is a valid one for a signature polynomial.
fn are_coefficients_valid(x: &[i16]) -> bool {
if x.len() != N {
Expand Down

0 comments on commit c8411da

Please sign in to comment.