mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-09 14:47:56 -05:00
chore(zk): check that crs group element at index n is 0
This commit is contained in:
committed by
Nicolas Sarlin
parent
9ee8259002
commit
786fe66495
@@ -97,6 +97,7 @@ pub trait CurveGroupOps<Zp>:
|
||||
+ core::ops::Sub<Self, Output = Self>
|
||||
+ core::ops::Neg<Output = Self>
|
||||
+ core::iter::Sum
|
||||
+ PartialEq
|
||||
{
|
||||
const ZERO: Self;
|
||||
const GENERATOR: Self;
|
||||
|
||||
@@ -124,7 +124,14 @@ impl<G: Curve> GroupElements<G> {
|
||||
}
|
||||
|
||||
/// Check if the elements are valid for their respective groups
|
||||
pub fn is_valid(&self) -> bool {
|
||||
pub fn is_valid(&self, n: usize) -> bool {
|
||||
if self.g_list.0.len() != n * 2
|
||||
|| self.g_hat_list.0.len() != n
|
||||
|| G::G1::projective(self.g_list[n + 1]) != G::G1::ZERO
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
let (g_list_valid, g_hat_list_valid) = rayon::join(
|
||||
|| self.g_list.0.par_iter().all(G::G1::validate_affine),
|
||||
|| self.g_hat_list.0.par_iter().all(G::G2::validate_affine),
|
||||
|
||||
@@ -189,7 +189,7 @@ impl<G: Curve> PublicParams<G> {
|
||||
/// - valid points of the curve
|
||||
/// - in the correct subgroup
|
||||
pub fn is_usable(&self) -> bool {
|
||||
self.g_lists.is_valid()
|
||||
self.g_lists.is_valid(self.n)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,8 +139,16 @@ where
|
||||
hash_z,
|
||||
hash_chi,
|
||||
} = compressed;
|
||||
|
||||
let uncompressed_g_lists = GroupElements::uncompress(g_lists)?;
|
||||
if G::G1::projective(uncompressed_g_lists.g_list[n + 1]) != G::G1::ZERO {
|
||||
return Err(InvalidSerializedPublicParamsError::InvalidGroupElements(
|
||||
InvalidSerializedGroupElementsError::MissingPuncteredElement,
|
||||
));
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
g_lists: GroupElements::uncompress(g_lists)?,
|
||||
g_lists: uncompressed_g_lists,
|
||||
D,
|
||||
n,
|
||||
d,
|
||||
@@ -166,6 +174,8 @@ where
|
||||
}
|
||||
|
||||
impl<G: Curve> PublicParams<G> {
|
||||
/// Builds a crs from raw elements. When the elements are received from an untrusted party, the
|
||||
/// resulting crs should be validated with [`Self::is_usable`]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn from_vec(
|
||||
g_list: Vec<Affine<G::Zp, G::G1>>,
|
||||
@@ -227,8 +237,9 @@ impl<G: Curve> PublicParams<G> {
|
||||
/// This means checking that the points are:
|
||||
/// - valid points of the curve
|
||||
/// - in the correct subgroup
|
||||
/// - the size of the list is correct and the element at index n is 0
|
||||
pub fn is_usable(&self) -> bool {
|
||||
self.g_lists.is_valid()
|
||||
self.g_lists.is_valid(self.n)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -775,6 +786,7 @@ fn prove_impl<G: Curve>(
|
||||
B_squared >= e_sqr_norm,
|
||||
"squared norm of error ({e_sqr_norm}) exceeds threshold ({B_squared})",
|
||||
);
|
||||
assert_eq!(G::G1::projective(g_list[n]), G::G1::ZERO);
|
||||
}
|
||||
|
||||
// FIXME: div_round
|
||||
@@ -3290,6 +3302,37 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// Test the `is_usable` method, that checks the correctness of the the crs
|
||||
#[test]
|
||||
fn test_crs_usable() {
|
||||
let PkeTestParameters {
|
||||
d,
|
||||
k,
|
||||
B,
|
||||
q,
|
||||
t,
|
||||
msbs_zero_padding_bit_count,
|
||||
} = PKEV2_TEST_PARAMS;
|
||||
|
||||
let rng = &mut StdRng::seed_from_u64(0);
|
||||
|
||||
let crs_k = k + 1 + (rng.gen::<usize>() % (d - k));
|
||||
|
||||
let public_param = crs_gen::<Curve>(d, crs_k, B, q, t, msbs_zero_padding_bit_count, rng);
|
||||
|
||||
assert!(public_param.is_usable());
|
||||
|
||||
let public_param_that_was_compressed =
|
||||
serialize_then_deserialize(&public_param, Compress::Yes).unwrap();
|
||||
|
||||
assert!(public_param_that_was_compressed.is_usable());
|
||||
|
||||
let mut bad_crs = public_param.clone();
|
||||
bad_crs.g_lists.g_list[public_param.n + 1] = bad_crs.g_lists.g_list[public_param.n];
|
||||
|
||||
assert!(!bad_crs.is_usable());
|
||||
}
|
||||
|
||||
/// Test the `is_usable` method, that checks the correctness of the EC points in the proof
|
||||
#[test]
|
||||
fn test_proof_usable() {
|
||||
|
||||
@@ -256,6 +256,7 @@ pub(crate) type SerializableFp12 = SerializableQuadExtField<SerializableFp6>;
|
||||
pub enum InvalidSerializedGroupElementsError {
|
||||
InvalidAffine(InvalidSerializedAffineError),
|
||||
InvalidGlistDimension(InvalidArraySizeError),
|
||||
MissingPuncteredElement,
|
||||
}
|
||||
|
||||
impl Display for InvalidSerializedGroupElementsError {
|
||||
@@ -267,6 +268,9 @@ impl Display for InvalidSerializedGroupElementsError {
|
||||
InvalidSerializedGroupElementsError::InvalidGlistDimension(arr_error) => {
|
||||
write!(f, "invalid number of elements in g_list: {arr_error}")
|
||||
}
|
||||
InvalidSerializedGroupElementsError::MissingPuncteredElement => {
|
||||
write!(f, "Element at index n in g_list should be 0")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,6 +282,7 @@ impl Error for InvalidSerializedGroupElementsError {
|
||||
InvalidSerializedGroupElementsError::InvalidGlistDimension(arr_error) => {
|
||||
Some(arr_error)
|
||||
}
|
||||
InvalidSerializedGroupElementsError::MissingPuncteredElement => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user