tfhe_zk_pok/
serialization.rs

1#![allow(non_snake_case)]
2
3use std::error::Error;
4use std::fmt::Display;
5use std::marker::PhantomData;
6
7use crate::backward_compatibility::{
8    SerializableAffineVersions, SerializableCubicExtFieldVersions, SerializableFpVersions,
9    SerializableGroupElementsVersions, SerializablePKEv1PublicParamsVersions,
10    SerializablePKEv2PublicParamsVersions, SerializableQuadExtFieldVersions,
11};
12use ark_ec::short_weierstrass::{Affine, SWCurveConfig};
13use ark_ec::AffineRepr;
14use ark_ff::{BigInt, Field, Fp, Fp2, Fp6, Fp6Config, FpConfig, QuadExtConfig, QuadExtField};
15use serde::{Deserialize, Serialize};
16use tfhe_versionable::Versionize;
17
18use crate::curve_api::{Curve, CurveGroupOps};
19use crate::proofs::pke::PublicParams as PKEv1PublicParams;
20use crate::proofs::pke_v2::{Bound, PublicParams as PKEv2PublicParams};
21use crate::proofs::GroupElements;
22
23/// Error returned when a conversion from a vec to a fixed size array failed because the vec size is
24/// incorrect
25#[derive(Debug)]
26pub struct InvalidArraySizeError {
27    expected_len: usize,
28    found_len: usize,
29}
30
31impl Display for InvalidArraySizeError {
32    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33        write!(
34            f,
35            "Invalid serialized array: found array of size {}, expected {}",
36            self.found_len, self.expected_len
37        )
38    }
39}
40
41impl Error for InvalidArraySizeError {}
42
43/// Tries to convert a Vec into a constant size array, and returns an [`InvalidArraySizeError`] if
44/// the size does not match
45pub(crate) fn try_vec_to_array<T, const N: usize>(
46    vec: Vec<T>,
47) -> Result<[T; N], InvalidArraySizeError> {
48    let len = vec.len();
49
50    vec.try_into().map_err(|_| InvalidArraySizeError {
51        expected_len: len,
52        found_len: N,
53    })
54}
55
56/// Serialization equivalent of the [`Fp`] struct, where the bigint is split into
57/// multiple u64.
58#[derive(Serialize, Deserialize, Versionize)]
59#[versionize(SerializableFpVersions)]
60pub struct SerializableFp {
61    val: Vec<u64>, // Use a Vec<u64> since serde does not support fixed size arrays with a generic
62}
63
64impl<P: FpConfig<N>, const N: usize> From<Fp<P, N>> for SerializableFp {
65    fn from(value: Fp<P, N>) -> Self {
66        Self {
67            val: value.0 .0.to_vec(),
68        }
69    }
70}
71
72impl<P: FpConfig<N>, const N: usize> TryFrom<SerializableFp> for Fp<P, N> {
73    type Error = InvalidArraySizeError;
74
75    fn try_from(value: SerializableFp) -> Result<Self, Self::Error> {
76        Ok(Fp(BigInt(try_vec_to_array(value.val)?), PhantomData))
77    }
78}
79
80#[derive(Debug)]
81pub enum InvalidSerializedAffineError {
82    InvalidFp(InvalidArraySizeError),
83    InvalidCompressedXCoordinate,
84}
85
86impl Display for InvalidSerializedAffineError {
87    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88        match self {
89            InvalidSerializedAffineError::InvalidFp(fp_error) => {
90                write!(f, "Invalid fp element in affine: {fp_error}")
91            }
92            InvalidSerializedAffineError::InvalidCompressedXCoordinate => {
93                write!(
94                    f,
95                    "Cannot uncompress affine: X coordinate does not belong to the curve"
96                )
97            }
98        }
99    }
100}
101
102impl Error for InvalidSerializedAffineError {
103    fn source(&self) -> Option<&(dyn Error + 'static)> {
104        match self {
105            InvalidSerializedAffineError::InvalidFp(fp_error) => Some(fp_error),
106            InvalidSerializedAffineError::InvalidCompressedXCoordinate => None,
107        }
108    }
109}
110
111impl From<InvalidArraySizeError> for InvalidSerializedAffineError {
112    fn from(value: InvalidArraySizeError) -> Self {
113        Self::InvalidFp(value)
114    }
115}
116
117/// Serialization equivalent to the [`Affine`], which support an optional compression mode
118/// where only the `x` coordinate is stored, and the `y` is computed on load.
119#[derive(Serialize, Deserialize, Versionize)]
120#[versionize(SerializableAffineVersions)]
121pub enum SerializableAffine<F> {
122    Infinity,
123    Compressed { x: F, take_largest_y: bool },
124    Uncompressed { x: F, y: F },
125}
126
127impl<F> SerializableAffine<F> {
128    #[allow(unused)]
129    pub fn uncompressed<BaseField: Into<F> + Field, C: SWCurveConfig<BaseField = BaseField>>(
130        value: Affine<C>,
131    ) -> Self {
132        if value.is_zero() {
133            Self::Infinity
134        } else {
135            Self::Uncompressed {
136                x: value.x.into(),
137                y: value.y.into(),
138            }
139        }
140    }
141
142    pub fn compressed<BaseField: Into<F> + Field, C: SWCurveConfig<BaseField = BaseField>>(
143        value: Affine<C>,
144    ) -> Self {
145        if value.is_zero() {
146            Self::Infinity
147        } else {
148            let take_largest_y = value.y > -value.y;
149            Self::Compressed {
150                x: value.x.into(),
151                take_largest_y,
152            }
153        }
154    }
155}
156
157impl<F, C: SWCurveConfig> TryFrom<SerializableAffine<F>> for Affine<C>
158where
159    F: TryInto<C::BaseField, Error = InvalidArraySizeError>,
160{
161    type Error = InvalidSerializedAffineError;
162
163    fn try_from(value: SerializableAffine<F>) -> Result<Self, Self::Error> {
164        match value {
165            SerializableAffine::Infinity => Ok(Self::zero()),
166            SerializableAffine::Compressed { x, take_largest_y } => {
167                Self::get_point_from_x_unchecked(x.try_into()?, take_largest_y)
168                    .ok_or(InvalidSerializedAffineError::InvalidCompressedXCoordinate)
169            }
170            SerializableAffine::Uncompressed { x, y } => {
171                Ok(Self::new_unchecked(x.try_into()?, y.try_into()?))
172            }
173        }
174    }
175}
176
177pub(crate) type SerializableG1Affine = SerializableAffine<SerializableFp>;
178
179#[derive(Serialize, Deserialize, Versionize)]
180#[versionize(SerializableQuadExtFieldVersions)]
181pub struct SerializableQuadExtField<F> {
182    c0: F,
183    c1: F,
184}
185
186pub(crate) type SerializableFp2 = SerializableQuadExtField<SerializableFp>;
187pub type SerializableG2Affine = SerializableAffine<SerializableFp2>;
188
189impl<F, P: QuadExtConfig> From<QuadExtField<P>> for SerializableQuadExtField<F>
190where
191    F: From<P::BaseField>,
192{
193    fn from(value: QuadExtField<P>) -> Self {
194        Self {
195            c0: value.c0.into(),
196            c1: value.c1.into(),
197        }
198    }
199}
200
201impl<F, P: QuadExtConfig> TryFrom<SerializableQuadExtField<F>> for QuadExtField<P>
202where
203    F: TryInto<P::BaseField, Error = InvalidArraySizeError>,
204{
205    type Error = InvalidArraySizeError;
206
207    fn try_from(value: SerializableQuadExtField<F>) -> Result<Self, Self::Error> {
208        Ok(QuadExtField {
209            c0: value.c0.try_into()?,
210            c1: value.c1.try_into()?,
211        })
212    }
213}
214
215#[derive(Serialize, Deserialize, Versionize)]
216#[versionize(SerializableCubicExtFieldVersions)]
217pub struct SerializableCubicExtField<F> {
218    c0: F,
219    c1: F,
220    c2: F,
221}
222
223pub(crate) type SerializableFp6 = SerializableCubicExtField<SerializableFp2>;
224
225impl<F, P6: Fp6Config> From<Fp6<P6>> for SerializableCubicExtField<F>
226where
227    F: From<Fp2<P6::Fp2Config>>,
228{
229    fn from(value: Fp6<P6>) -> Self {
230        Self {
231            c0: value.c0.into(),
232            c1: value.c1.into(),
233            c2: value.c2.into(),
234        }
235    }
236}
237
238impl<F, P6: Fp6Config> TryFrom<SerializableCubicExtField<F>> for Fp6<P6>
239where
240    F: TryInto<Fp2<P6::Fp2Config>, Error = InvalidArraySizeError>,
241{
242    type Error = InvalidArraySizeError;
243
244    fn try_from(value: SerializableCubicExtField<F>) -> Result<Self, Self::Error> {
245        Ok(Fp6 {
246            c0: value.c0.try_into()?,
247            c1: value.c1.try_into()?,
248            c2: value.c2.try_into()?,
249        })
250    }
251}
252
253pub(crate) type SerializableFp12 = SerializableQuadExtField<SerializableFp6>;
254
255#[derive(Debug)]
256pub enum InvalidSerializedGroupElementsError {
257    InvalidAffine(InvalidSerializedAffineError),
258    InvalidGlistDimension(InvalidArraySizeError),
259    MissingPuncteredElement,
260}
261
262impl Display for InvalidSerializedGroupElementsError {
263    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
264        match self {
265            InvalidSerializedGroupElementsError::InvalidAffine(affine_error) => {
266                write!(f, "Invalid Affine in GroupElement: {affine_error}")
267            }
268            InvalidSerializedGroupElementsError::InvalidGlistDimension(arr_error) => {
269                write!(f, "invalid number of elements in g_list: {arr_error}")
270            }
271            InvalidSerializedGroupElementsError::MissingPuncteredElement => {
272                write!(f, "Element at index n in g_list should be 0")
273            }
274        }
275    }
276}
277
278impl Error for InvalidSerializedGroupElementsError {
279    fn source(&self) -> Option<&(dyn Error + 'static)> {
280        match self {
281            InvalidSerializedGroupElementsError::InvalidAffine(affine_error) => Some(affine_error),
282            InvalidSerializedGroupElementsError::InvalidGlistDimension(arr_error) => {
283                Some(arr_error)
284            }
285            InvalidSerializedGroupElementsError::MissingPuncteredElement => None,
286        }
287    }
288}
289
290impl From<InvalidSerializedAffineError> for InvalidSerializedGroupElementsError {
291    fn from(value: InvalidSerializedAffineError) -> Self {
292        Self::InvalidAffine(value)
293    }
294}
295
296#[derive(Serialize, Deserialize, Versionize)]
297#[versionize(SerializableGroupElementsVersions)]
298pub(crate) struct SerializableGroupElements {
299    pub(crate) g_list: Vec<SerializableG1Affine>,
300    pub(crate) g_hat_list: Vec<SerializableG2Affine>,
301}
302
303impl<G: Curve> From<GroupElements<G>> for SerializableGroupElements
304where
305    <G::G1 as CurveGroupOps<G::Zp>>::Affine: Into<SerializableG1Affine>,
306    <G::G2 as CurveGroupOps<G::Zp>>::Affine: Into<SerializableG2Affine>,
307{
308    fn from(value: GroupElements<G>) -> Self {
309        let mut g_list = Vec::new();
310        let mut g_hat_list = Vec::new();
311        for idx in 0..value.message_len {
312            g_list.push(value.g_list[(idx * 2) + 1].into());
313            g_list.push(value.g_list[(idx * 2) + 2].into());
314            g_hat_list.push(value.g_hat_list[idx + 1].into())
315        }
316
317        Self { g_list, g_hat_list }
318    }
319}
320
321impl<G: Curve> TryFrom<SerializableGroupElements> for GroupElements<G>
322where
323    <G::G1 as CurveGroupOps<G::Zp>>::Affine:
324        TryFrom<SerializableG1Affine, Error = InvalidSerializedAffineError>,
325    <G::G2 as CurveGroupOps<G::Zp>>::Affine:
326        TryFrom<SerializableG2Affine, Error = InvalidSerializedAffineError>,
327{
328    type Error = InvalidSerializedGroupElementsError;
329
330    fn try_from(value: SerializableGroupElements) -> Result<Self, Self::Error> {
331        if value.g_list.len() != value.g_hat_list.len() * 2 {
332            return Err(InvalidSerializedGroupElementsError::InvalidGlistDimension(
333                InvalidArraySizeError {
334                    expected_len: value.g_hat_list.len() * 2,
335                    found_len: value.g_list.len(),
336                },
337            ));
338        }
339
340        let g_list = value
341            .g_list
342            .into_iter()
343            .map(<G::G1 as CurveGroupOps<G::Zp>>::Affine::try_from)
344            .collect::<Result<_, InvalidSerializedAffineError>>()?;
345        let g_hat_list = value
346            .g_hat_list
347            .into_iter()
348            .map(<G::G2 as CurveGroupOps<G::Zp>>::Affine::try_from)
349            .collect::<Result<_, InvalidSerializedAffineError>>()?;
350
351        Ok(Self::from_vec(g_list, g_hat_list))
352    }
353}
354
355#[derive(Debug)]
356pub enum InvalidSerializedPublicParamsError {
357    InvalidGroupElements(InvalidSerializedGroupElementsError),
358    InvalidHashDimension(InvalidArraySizeError),
359}
360
361impl Display for InvalidSerializedPublicParamsError {
362    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
363        match self {
364            InvalidSerializedPublicParamsError::InvalidGroupElements(group_error) => {
365                write!(f, "Invalid PublicParams: {group_error}")
366            }
367            InvalidSerializedPublicParamsError::InvalidHashDimension(arr_error) => {
368                write!(f, "invalid size of hash: {arr_error}")
369            }
370        }
371    }
372}
373
374impl Error for InvalidSerializedPublicParamsError {
375    fn source(&self) -> Option<&(dyn Error + 'static)> {
376        match self {
377            InvalidSerializedPublicParamsError::InvalidGroupElements(group_error) => {
378                Some(group_error)
379            }
380            InvalidSerializedPublicParamsError::InvalidHashDimension(arr_error) => Some(arr_error),
381        }
382    }
383}
384
385impl From<InvalidSerializedGroupElementsError> for InvalidSerializedPublicParamsError {
386    fn from(value: InvalidSerializedGroupElementsError) -> Self {
387        Self::InvalidGroupElements(value)
388    }
389}
390
391impl From<InvalidArraySizeError> for InvalidSerializedPublicParamsError {
392    fn from(value: InvalidArraySizeError) -> Self {
393        Self::InvalidHashDimension(value)
394    }
395}
396
397#[derive(serde::Serialize, serde::Deserialize, Versionize)]
398#[versionize(SerializablePKEv2PublicParamsVersions)]
399pub struct SerializablePKEv2PublicParams {
400    pub(crate) g_lists: SerializableGroupElements,
401    pub(crate) D: usize,
402    pub n: usize,
403    pub d: usize,
404    pub k: usize,
405    pub B_bound_squared: u128,
406    pub B_inf: u64,
407    pub q: u64,
408    pub t: u64,
409    pub msbs_zero_padding_bit_count: u64,
410    pub bound_type: Bound,
411    // We use Vec<u8> since serde does not support fixed size arrays of 256 elements
412    pub(crate) hash: Vec<u8>,
413    pub(crate) hash_R: Vec<u8>,
414    pub(crate) hash_t: Vec<u8>,
415    pub(crate) hash_w: Vec<u8>,
416    pub(crate) hash_agg: Vec<u8>,
417    pub(crate) hash_lmap: Vec<u8>,
418    pub(crate) hash_phi: Vec<u8>,
419    pub(crate) hash_xi: Vec<u8>,
420    pub(crate) hash_z: Vec<u8>,
421    pub(crate) hash_chi: Vec<u8>,
422}
423
424impl<G: Curve> From<PKEv2PublicParams<G>> for SerializablePKEv2PublicParams
425where
426    GroupElements<G>: Into<SerializableGroupElements>,
427{
428    fn from(value: PKEv2PublicParams<G>) -> Self {
429        let PKEv2PublicParams {
430            g_lists,
431            D,
432            n,
433            d,
434            k,
435            B_bound_squared,
436            B_inf,
437            q,
438            t,
439            msbs_zero_padding_bit_count,
440            bound_type,
441            hash,
442            hash_R,
443            hash_t,
444            hash_w,
445            hash_agg,
446            hash_lmap,
447            hash_phi,
448            hash_xi,
449            hash_z,
450            hash_chi,
451        } = value;
452        Self {
453            g_lists: g_lists.into(),
454            D,
455            n,
456            d,
457            k,
458            B_bound_squared,
459            B_inf,
460            q,
461            t,
462            msbs_zero_padding_bit_count,
463            bound_type,
464            hash: hash.to_vec(),
465            hash_R: hash_R.to_vec(),
466            hash_t: hash_t.to_vec(),
467            hash_w: hash_w.to_vec(),
468            hash_agg: hash_agg.to_vec(),
469            hash_lmap: hash_lmap.to_vec(),
470            hash_phi: hash_phi.to_vec(),
471            hash_xi: hash_xi.to_vec(),
472            hash_z: hash_z.to_vec(),
473            hash_chi: hash_chi.to_vec(),
474        }
475    }
476}
477
478impl<G: Curve> TryFrom<SerializablePKEv2PublicParams> for PKEv2PublicParams<G>
479where
480    GroupElements<G>:
481        TryFrom<SerializableGroupElements, Error = InvalidSerializedGroupElementsError>,
482{
483    type Error = InvalidSerializedPublicParamsError;
484
485    fn try_from(value: SerializablePKEv2PublicParams) -> Result<Self, Self::Error> {
486        let SerializablePKEv2PublicParams {
487            g_lists,
488            D,
489            n,
490            d,
491            k,
492            B_bound_squared,
493            B_inf,
494            q,
495            t,
496            msbs_zero_padding_bit_count,
497            bound_type,
498            hash,
499            hash_R,
500            hash_t,
501            hash_w,
502            hash_agg,
503            hash_lmap,
504            hash_phi,
505            hash_xi,
506            hash_z,
507            hash_chi,
508        } = value;
509        Ok(Self {
510            g_lists: g_lists.try_into()?,
511            D,
512            n,
513            d,
514            k,
515            B_bound_squared,
516            B_inf,
517            q,
518            t,
519            msbs_zero_padding_bit_count,
520            bound_type,
521            hash: try_vec_to_array(hash)?,
522            hash_R: try_vec_to_array(hash_R)?,
523            hash_t: try_vec_to_array(hash_t)?,
524            hash_w: try_vec_to_array(hash_w)?,
525            hash_agg: try_vec_to_array(hash_agg)?,
526            hash_lmap: try_vec_to_array(hash_lmap)?,
527            hash_phi: try_vec_to_array(hash_phi)?,
528            hash_xi: try_vec_to_array(hash_xi)?,
529            hash_z: try_vec_to_array(hash_z)?,
530            hash_chi: try_vec_to_array(hash_chi)?,
531        })
532    }
533}
534
535#[derive(serde::Serialize, serde::Deserialize, Versionize)]
536#[versionize(SerializablePKEv1PublicParamsVersions)]
537pub struct SerializablePKEv1PublicParams {
538    pub(crate) g_lists: SerializableGroupElements,
539    pub(crate) big_d: usize,
540    pub n: usize,
541    pub d: usize,
542    pub k: usize,
543    pub b: u64,
544    pub b_r: u64,
545    pub q: u64,
546    pub t: u64,
547    pub msbs_zero_padding_bit_count: u64,
548    // We use Vec<u8> since serde does not support fixed size arrays of 256 elements
549    pub(crate) hash: Vec<u8>,
550    pub(crate) hash_t: Vec<u8>,
551    pub(crate) hash_agg: Vec<u8>,
552    pub(crate) hash_lmap: Vec<u8>,
553    pub(crate) hash_z: Vec<u8>,
554    pub(crate) hash_w: Vec<u8>,
555}
556
557impl<G: Curve> From<PKEv1PublicParams<G>> for SerializablePKEv1PublicParams
558where
559    GroupElements<G>: Into<SerializableGroupElements>,
560{
561    fn from(value: PKEv1PublicParams<G>) -> Self {
562        let PKEv1PublicParams {
563            g_lists,
564            big_d,
565            n,
566            d,
567            k,
568            b,
569            b_r,
570            q,
571            t,
572            msbs_zero_padding_bit_count,
573            hash,
574            hash_t,
575            hash_agg,
576            hash_lmap,
577            hash_z,
578            hash_w,
579        } = value;
580        Self {
581            g_lists: g_lists.into(),
582            big_d,
583            n,
584            d,
585            k,
586            b,
587            b_r,
588            q,
589            t,
590            msbs_zero_padding_bit_count,
591            hash: hash.to_vec(),
592            hash_t: hash_t.to_vec(),
593            hash_agg: hash_agg.to_vec(),
594            hash_lmap: hash_lmap.to_vec(),
595            hash_z: hash_z.to_vec(),
596            hash_w: hash_w.to_vec(),
597        }
598    }
599}
600
601impl<G: Curve> TryFrom<SerializablePKEv1PublicParams> for PKEv1PublicParams<G>
602where
603    GroupElements<G>:
604        TryFrom<SerializableGroupElements, Error = InvalidSerializedGroupElementsError>,
605{
606    type Error = InvalidSerializedPublicParamsError;
607
608    fn try_from(value: SerializablePKEv1PublicParams) -> Result<Self, Self::Error> {
609        let SerializablePKEv1PublicParams {
610            g_lists,
611            big_d,
612            n,
613            d,
614            k,
615            b,
616            b_r,
617            q,
618            t,
619            msbs_zero_padding_bit_count,
620            hash,
621            hash_t,
622            hash_agg,
623            hash_lmap,
624            hash_z,
625            hash_w,
626        } = value;
627        Ok(Self {
628            g_lists: g_lists.try_into()?,
629            big_d,
630            n,
631            d,
632            k,
633            b,
634            b_r,
635            q,
636            t,
637            msbs_zero_padding_bit_count,
638            hash: try_vec_to_array(hash)?,
639            hash_t: try_vec_to_array(hash_t)?,
640            hash_agg: try_vec_to_array(hash_agg)?,
641            hash_lmap: try_vec_to_array(hash_lmap)?,
642            hash_z: try_vec_to_array(hash_z)?,
643            hash_w: try_vec_to_array(hash_w)?,
644        })
645    }
646}