diff --git a/tfhe-zk-pok/src/backward_compatibility/mod.rs b/tfhe-zk-pok/src/backward_compatibility/mod.rs index d06c2c222..a827cccb1 100644 --- a/tfhe-zk-pok/src/backward_compatibility/mod.rs +++ b/tfhe-zk-pok/src/backward_compatibility/mod.rs @@ -11,14 +11,9 @@ use std::fmt::Display; use tfhe_versionable::{Upgrade, Version, VersionsDispatch}; use crate::curve_api::Curve; -use crate::four_squares::sqr; use crate::proofs::pke_v2::Bound; use crate::proofs::GroupElements; -use crate::serialization::{ - SerializableAffine, SerializableCubicExtField, SerializableFp, SerializableFp2, - SerializableFp6, SerializableGroupElements, SerializablePKEv1PublicParams, - SerializablePKEv2PublicParams, SerializableQuadExtField, -}; +use crate::serialization::*; #[derive(VersionsDispatch)] pub enum SerializableAffineVersions { @@ -73,49 +68,35 @@ pub(crate) enum SerializableGroupElementsVersions { #[derive(Version)] pub struct SerializablePKEv2PublicParamsV0 { - pub(crate) g_lists: SerializableGroupElements, - pub(crate) D: usize, - pub n: usize, - pub d: usize, - pub k: usize, - pub B: u64, - pub B_r: u64, - pub B_bound: u64, - pub m_bound: usize, - pub q: u64, - pub t: u64, - pub msbs_zero_padding_bit_count: u64, + g_lists: SerializableGroupElements, + D: usize, + n: usize, + d: usize, + k: usize, + B_bound_squared: u128, + B_inf: u64, + q: u64, + t: u64, + msbs_zero_padding_bit_count: u64, + bound_type: Bound, // We use Vec since serde does not support fixed size arrays of 256 elements - pub(crate) hash: Vec, - pub(crate) hash_R: Vec, - pub(crate) hash_t: Vec, - pub(crate) hash_w: Vec, - pub(crate) hash_agg: Vec, - pub(crate) hash_lmap: Vec, - pub(crate) hash_phi: Vec, - pub(crate) hash_xi: Vec, - pub(crate) hash_z: Vec, - pub(crate) hash_chi: Vec, + hash: Vec, + hash_R: Vec, + hash_t: Vec, + hash_w: Vec, + hash_agg: Vec, + hash_lmap: Vec, + hash_phi: Vec, + hash_xi: Vec, + hash_z: Vec, + hash_chi: Vec, } impl Upgrade for SerializablePKEv2PublicParamsV0 { type Error = Infallible; fn upgrade(self) -> Result { - let slack_factor = (self.d + self.k).isqrt() as u64; - let B_inf = self.B / slack_factor; - Ok(SerializablePKEv2PublicParams { - g_lists: self.g_lists, - D: self.D, - n: self.n, - d: self.d, - k: self.k, - B_bound_squared: sqr(self.B_bound), - B_inf, - q: self.q, - t: self.t, - msbs_zero_padding_bit_count: self.msbs_zero_padding_bit_count, - bound_type: Bound::CS, + let domain_separators = SerializablePKEv2DomainSeparators { hash: self.hash, hash_R: self.hash_R, hash_t: self.hash_t, @@ -126,18 +107,96 @@ impl Upgrade for SerializablePKEv2PublicParamsV0 hash_xi: self.hash_xi, hash_z: self.hash_z, hash_chi: self.hash_chi, + }; + + Ok(SerializablePKEv2PublicParams { + g_lists: self.g_lists, + D: self.D, + n: self.n, + d: self.d, + k: self.k, + B_bound_squared: self.B_bound_squared, + B_inf: self.B_inf, + q: self.q, + t: self.t, + msbs_zero_padding_bit_count: self.msbs_zero_padding_bit_count, + bound_type: self.bound_type, + sid: None, + domain_separators, }) } } #[derive(VersionsDispatch)] pub enum SerializablePKEv2PublicParamsVersions { - V0(SerializablePKEv2PublicParams), + V0(SerializablePKEv2PublicParamsV0), + V1(SerializablePKEv2PublicParams), +} + +#[derive(VersionsDispatch)] +pub enum SerializablePKEv2DomainSeparatorsVersions { + V0(SerializablePKEv2DomainSeparators), +} + +#[derive(Version)] +pub struct SerializablePKEv1PublicParamsV0 { + g_lists: SerializableGroupElements, + big_d: usize, + n: usize, + d: usize, + k: usize, + b: u64, + b_r: u64, + q: u64, + t: u64, + msbs_zero_padding_bit_count: u64, + hash: Vec, + hash_t: Vec, + hash_agg: Vec, + hash_lmap: Vec, + hash_z: Vec, + hash_w: Vec, +} + +impl Upgrade for SerializablePKEv1PublicParamsV0 { + type Error = Infallible; + + fn upgrade(self) -> Result { + let domain_separators = SerializablePKEv1DomainSeparators { + hash: self.hash, + hash_t: self.hash_t, + hash_agg: self.hash_agg, + hash_lmap: self.hash_lmap, + hash_w: self.hash_w, + hash_z: self.hash_z, + }; + + Ok(SerializablePKEv1PublicParams { + g_lists: self.g_lists, + big_d: self.big_d, + n: self.n, + d: self.d, + k: self.k, + b: self.b, + b_r: self.b_r, + q: self.q, + t: self.t, + msbs_zero_padding_bit_count: self.msbs_zero_padding_bit_count, + sid: None, + domain_separators, + }) + } } #[derive(VersionsDispatch)] pub enum SerializablePKEv1PublicParamsVersions { - V0(SerializablePKEv1PublicParams), + V0(SerializablePKEv1PublicParamsV0), + V1(SerializablePKEv1PublicParams), +} + +#[derive(VersionsDispatch)] +pub enum SerializablePKEv1DomainSeparatorsVersions { + V0(SerializablePKEv1DomainSeparators), } #[derive(VersionsDispatch)] diff --git a/tfhe-zk-pok/src/proofs/binary.rs b/tfhe-zk-pok/src/proofs/binary.rs index 5fc684b6a..a29c187a3 100644 --- a/tfhe-zk-pok/src/proofs/binary.rs +++ b/tfhe-zk-pok/src/proofs/binary.rs @@ -3,18 +3,18 @@ use super::*; #[derive(Clone, Debug)] pub struct PublicParams { g_lists: GroupElements, - hash: [u8; HASH_METADATA_LEN_BYTES], - hash_t: [u8; HASH_METADATA_LEN_BYTES], - hash_agg: [u8; HASH_METADATA_LEN_BYTES], + hash: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_t: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_agg: [u8; LEGACY_HASH_DS_LEN_BYTES], } impl PublicParams { pub fn from_vec( g_list: Vec>, g_hat_list: Vec>, - hash: [u8; HASH_METADATA_LEN_BYTES], - hash_t: [u8; HASH_METADATA_LEN_BYTES], - hash_agg: [u8; HASH_METADATA_LEN_BYTES], + hash: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_t: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_agg: [u8; LEGACY_HASH_DS_LEN_BYTES], ) -> Self { Self { g_lists: GroupElements::from_vec(g_list, g_hat_list), diff --git a/tfhe-zk-pok/src/proofs/mod.rs b/tfhe-zk-pok/src/proofs/mod.rs index 1bd9b448d..73e3f2cd7 100644 --- a/tfhe-zk-pok/src/proofs/mod.rs +++ b/tfhe-zk-pok/src/proofs/mod.rs @@ -295,7 +295,36 @@ where } } -pub const HASH_METADATA_LEN_BYTES: usize = 256; +/// Len of the "domain separator" fields used with the sha3 XoF PRNG +pub const HASH_DS_LEN_BYTES: usize = 8; + +pub const LEGACY_HASH_DS_LEN_BYTES: usize = 256; + +/// A unique id that is used to tie the hash functions to a specific CRS +#[derive(Debug, Clone, Copy)] +// This is an option for backward compatibility reasons +pub(crate) struct Sid(pub(crate) Option); + +impl Sid { + fn new(rng: &mut dyn RngCore) -> Self { + Self(Some(rng.gen())) + } + + fn to_le_bytes(self) -> SidBytes { + self.0 + .map(|val| SidBytes(Some(val.to_le_bytes()))) + .unwrap_or_default() + } +} + +#[derive(Default)] +struct SidBytes(Option<[u8; 16]>); + +impl SidBytes { + fn as_slice(&self) -> &[u8] { + self.0.as_ref().map(|val| val.as_slice()).unwrap_or(&[]) + } +} // The verifier is meant to be executed on a large server with a high number of core. However, some // arkworks operations do not scale well in that case, and we actually see decreased performance diff --git a/tfhe-zk-pok/src/proofs/pke.rs b/tfhe-zk-pok/src/proofs/pke.rs index acb950e27..a61618277 100644 --- a/tfhe-zk-pok/src/proofs/pke.rs +++ b/tfhe-zk-pok/src/proofs/pke.rs @@ -5,8 +5,8 @@ use crate::backward_compatibility::pke::{ ComputeLoadProofFieldVersions, ProofVersions, }; use crate::serialization::{ - try_vec_to_array, InvalidSerializedAffineError, InvalidSerializedPublicParamsError, - SerializableGroupElements, SerializablePKEv1PublicParams, + InvalidSerializedAffineError, InvalidSerializedPublicParamsError, SerializableGroupElements, + SerializablePKEv1PublicParams, }; use super::*; @@ -40,12 +40,91 @@ pub struct PublicParams { pub q: u64, pub t: u64, pub msbs_zero_padding_bit_count: u64, - pub(crate) hash: [u8; HASH_METADATA_LEN_BYTES], - pub(crate) hash_t: [u8; HASH_METADATA_LEN_BYTES], - pub(crate) hash_agg: [u8; HASH_METADATA_LEN_BYTES], - pub(crate) hash_lmap: [u8; HASH_METADATA_LEN_BYTES], - pub(crate) hash_z: [u8; HASH_METADATA_LEN_BYTES], - pub(crate) hash_w: [u8; HASH_METADATA_LEN_BYTES], + pub(crate) sid: Sid, + pub(crate) domain_separators: PKEv1DomainSeparators, +} + +#[derive(Clone, Debug)] +pub(crate) enum PKEv1DomainSeparators { + Legacy(Box), + Short(ShortPKEv1DomainSeparators), +} + +impl PKEv1DomainSeparators { + pub(crate) fn new(rng: &mut dyn RngCore) -> Self { + let ds = ShortPKEv1DomainSeparators { + hash: core::array::from_fn(|_| rng.gen()), + hash_t: core::array::from_fn(|_| rng.gen()), + hash_agg: core::array::from_fn(|_| rng.gen()), + hash_lmap: core::array::from_fn(|_| rng.gen()), + hash_z: core::array::from_fn(|_| rng.gen()), + hash_w: core::array::from_fn(|_| rng.gen()), + }; + + Self::Short(ds) + } + + pub(crate) fn hash(&self) -> &[u8] { + match self { + PKEv1DomainSeparators::Legacy(ds) => &ds.hash, + PKEv1DomainSeparators::Short(ds) => &ds.hash, + } + } + + pub(crate) fn hash_t(&self) -> &[u8] { + match self { + PKEv1DomainSeparators::Legacy(ds) => &ds.hash_t, + PKEv1DomainSeparators::Short(ds) => &ds.hash_t, + } + } + + pub(crate) fn hash_agg(&self) -> &[u8] { + match self { + PKEv1DomainSeparators::Legacy(ds) => &ds.hash_agg, + PKEv1DomainSeparators::Short(ds) => &ds.hash_agg, + } + } + + pub(crate) fn hash_lmap(&self) -> &[u8] { + match self { + PKEv1DomainSeparators::Legacy(ds) => &ds.hash_lmap, + PKEv1DomainSeparators::Short(ds) => &ds.hash_lmap, + } + } + + pub(crate) fn hash_w(&self) -> &[u8] { + match self { + PKEv1DomainSeparators::Legacy(ds) => &ds.hash_w, + PKEv1DomainSeparators::Short(ds) => &ds.hash_w, + } + } + + pub(crate) fn hash_z(&self) -> &[u8] { + match self { + PKEv1DomainSeparators::Legacy(ds) => &ds.hash_z, + PKEv1DomainSeparators::Short(ds) => &ds.hash_z, + } + } +} + +#[derive(Clone, Debug)] +pub struct LegacyPKEv1DomainSeparators { + pub(crate) hash: [u8; LEGACY_HASH_DS_LEN_BYTES], + pub(crate) hash_t: [u8; LEGACY_HASH_DS_LEN_BYTES], + pub(crate) hash_agg: [u8; LEGACY_HASH_DS_LEN_BYTES], + pub(crate) hash_lmap: [u8; LEGACY_HASH_DS_LEN_BYTES], + pub(crate) hash_w: [u8; LEGACY_HASH_DS_LEN_BYTES], + pub(crate) hash_z: [u8; LEGACY_HASH_DS_LEN_BYTES], +} + +#[derive(Clone, Debug)] +pub struct ShortPKEv1DomainSeparators { + pub(crate) hash: [u8; HASH_DS_LEN_BYTES], + pub(crate) hash_t: [u8; HASH_DS_LEN_BYTES], + pub(crate) hash_agg: [u8; HASH_DS_LEN_BYTES], + pub(crate) hash_lmap: [u8; HASH_DS_LEN_BYTES], + pub(crate) hash_z: [u8; HASH_DS_LEN_BYTES], + pub(crate) hash_w: [u8; HASH_DS_LEN_BYTES], } impl Compressible for PublicParams @@ -71,12 +150,8 @@ where q, t, msbs_zero_padding_bit_count, - hash, - hash_t, - hash_agg, - hash_lmap, - hash_z, - hash_w, + sid, + domain_separators, } = self; SerializablePKEv1PublicParams { g_lists: g_lists.compress(), @@ -89,12 +164,8 @@ where q: *q, t: *t, msbs_zero_padding_bit_count: *msbs_zero_padding_bit_count, - hash: hash.to_vec(), - hash_t: hash_t.to_vec(), - hash_agg: hash_agg.to_vec(), - hash_lmap: hash_lmap.to_vec(), - hash_z: hash_z.to_vec(), - hash_w: hash_w.to_vec(), + sid: sid.0, + domain_separators: domain_separators.clone().into(), } } @@ -110,12 +181,8 @@ where q, t, msbs_zero_padding_bit_count, - hash, - hash_t, - hash_agg, - hash_lmap, - hash_z, - hash_w, + sid, + domain_separators, } = compressed; Ok(Self { g_lists: GroupElements::uncompress(g_lists)?, @@ -128,12 +195,8 @@ where q, t, msbs_zero_padding_bit_count, - hash: try_vec_to_array(hash)?, - hash_t: try_vec_to_array(hash_t)?, - hash_agg: try_vec_to_array(hash_agg)?, - hash_lmap: try_vec_to_array(hash_lmap)?, - hash_z: try_vec_to_array(hash_z)?, - hash_w: try_vec_to_array(hash_w)?, + sid: Sid(sid), + domain_separators: domain_separators.try_into()?, }) } } @@ -152,12 +215,13 @@ impl PublicParams { q: u64, t: u64, msbs_zero_padding_bit_count: u64, - hash: [u8; HASH_METADATA_LEN_BYTES], - hash_t: [u8; HASH_METADATA_LEN_BYTES], - hash_agg: [u8; HASH_METADATA_LEN_BYTES], - hash_lmap: [u8; HASH_METADATA_LEN_BYTES], - hash_z: [u8; HASH_METADATA_LEN_BYTES], - hash_w: [u8; HASH_METADATA_LEN_BYTES], + sid: u128, + hash: [u8; HASH_DS_LEN_BYTES], + hash_t: [u8; HASH_DS_LEN_BYTES], + hash_agg: [u8; HASH_DS_LEN_BYTES], + hash_lmap: [u8; HASH_DS_LEN_BYTES], + hash_z: [u8; HASH_DS_LEN_BYTES], + hash_w: [u8; HASH_DS_LEN_BYTES], ) -> Self { Self { g_lists: GroupElements::::from_vec(g_list, g_hat_list), @@ -170,12 +234,15 @@ impl PublicParams { q, t, msbs_zero_padding_bit_count, - hash, - hash_t, - hash_agg, - hash_lmap, - hash_z, - hash_w, + sid: Sid(Some(sid)), + domain_separators: PKEv1DomainSeparators::Short(ShortPKEv1DomainSeparators { + hash, + hash_t, + hash_agg, + hash_lmap, + hash_z, + hash_w, + }), } } @@ -427,12 +494,8 @@ pub fn crs_gen( q, t, msbs_zero_padding_bit_count, - hash: core::array::from_fn(|_| rng.gen()), - hash_t: core::array::from_fn(|_| rng.gen()), - hash_agg: core::array::from_fn(|_| rng.gen()), - hash_lmap: core::array::from_fn(|_| rng.gen()), - hash_z: core::array::from_fn(|_| rng.gen()), - hash_w: core::array::from_fn(|_| rng.gen()), + sid: Sid::new(rng), + domain_separators: PKEv1DomainSeparators::new(rng), } } @@ -504,12 +567,8 @@ fn prove_impl( t, msbs_zero_padding_bit_count, k: k_max, - ref hash, - ref hash_t, - ref hash_agg, - ref hash_lmap, - ref hash_z, - ref hash_w, + sid, + domain_separators: ref ds, } = public.0; let g_list = &g_lists.g_list; let g_hat_list = &g_lists.g_hat_list; @@ -597,7 +656,13 @@ fn prove_impl( let mut y = vec![G::Zp::ZERO; n]; G::Zp::hash( &mut y, - &[hash, metadata, x_bytes, c_hat.to_le_bytes().as_ref()], + &[ + ds.hash(), + sid.to_le_bytes().as_slice(), + metadata, + x_bytes, + c_hat.to_le_bytes().as_ref(), + ], ); let y = OneBased(y); @@ -610,7 +675,8 @@ fn prove_impl( G::Zp::hash( &mut theta, &[ - hash_lmap, + ds.hash_lmap(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, c_hat.to_le_bytes().as_ref(), @@ -642,7 +708,8 @@ fn prove_impl( G::Zp::hash_128bit( &mut t, &[ - hash_t, + ds.hash_t(), + sid.to_le_bytes().as_slice(), metadata, &(1..n + 1) .flat_map(|i| y[i].to_le_bytes().as_ref().to_vec()) @@ -658,7 +725,8 @@ fn prove_impl( G::Zp::hash( &mut delta, &[ - hash_agg, + ds.hash_agg(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, c_hat.to_le_bytes().as_ref(), @@ -737,7 +805,8 @@ fn prove_impl( G::Zp::hash( core::array::from_mut(&mut z), &[ - hash_z, + ds.hash_z(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, c_hat.to_le_bytes().as_ref(), @@ -778,7 +847,8 @@ fn prove_impl( G::Zp::hash( core::array::from_mut(&mut w), &[ - hash_w, + ds.hash_w(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, c_hat.to_le_bytes().as_ref(), @@ -984,12 +1054,8 @@ pub fn verify( t, msbs_zero_padding_bit_count, k: k_max, - ref hash, - ref hash_t, - ref hash_agg, - ref hash_lmap, - ref hash_z, - ref hash_w, + sid, + domain_separators: ref ds, } = public.0; let g_list = &g_lists.g_list; let g_hat_list = &g_lists.g_hat_list; @@ -1039,7 +1105,13 @@ pub fn verify( let mut y = vec![G::Zp::ZERO; n]; G::Zp::hash( &mut y, - &[hash, metadata, x_bytes, c_hat.to_le_bytes().as_ref()], + &[ + ds.hash(), + sid.to_le_bytes().as_slice(), + metadata, + x_bytes, + c_hat.to_le_bytes().as_ref(), + ], ); let y = OneBased(y); @@ -1047,7 +1119,8 @@ pub fn verify( G::Zp::hash( &mut theta, &[ - hash_lmap, + ds.hash_lmap(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, c_hat.to_le_bytes().as_ref(), @@ -1084,7 +1157,8 @@ pub fn verify( G::Zp::hash_128bit( &mut t, &[ - hash_t, + ds.hash_t(), + sid.to_le_bytes().as_slice(), metadata, &(1..n + 1) .flat_map(|i| y[i].to_le_bytes().as_ref().to_vec()) @@ -1100,7 +1174,8 @@ pub fn verify( G::Zp::hash( &mut delta, &[ - hash_agg, + ds.hash_agg(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, c_hat.to_le_bytes().as_ref(), @@ -1120,7 +1195,8 @@ pub fn verify( G::Zp::hash( core::array::from_mut(&mut z), &[ - hash_z, + ds.hash_z(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, c_hat.to_le_bytes().as_ref(), @@ -1173,7 +1249,8 @@ pub fn verify( G::Zp::hash( core::array::from_mut(&mut w), &[ - hash_w, + ds.hash_w(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, c_hat.to_le_bytes().as_ref(), diff --git a/tfhe-zk-pok/src/proofs/pke_v2.rs b/tfhe-zk-pok/src/proofs/pke_v2.rs index d14001cc6..e6dd725e9 100644 --- a/tfhe-zk-pok/src/proofs/pke_v2.rs +++ b/tfhe-zk-pok/src/proofs/pke_v2.rs @@ -7,8 +7,8 @@ use crate::backward_compatibility::BoundVersions; use crate::curve_api::{CompressedG1, CompressedG2}; use crate::four_squares::*; use crate::serialization::{ - try_vec_to_array, InvalidSerializedAffineError, InvalidSerializedPublicParamsError, - SerializableGroupElements, SerializablePKEv2PublicParams, + InvalidSerializedAffineError, InvalidSerializedPublicParamsError, SerializableGroupElements, + SerializablePKEv2PublicParams, }; use core::marker::PhantomData; @@ -43,16 +43,131 @@ pub struct PublicParams { pub t: u64, pub msbs_zero_padding_bit_count: u64, pub bound_type: Bound, - pub(crate) hash: [u8; HASH_METADATA_LEN_BYTES], - pub(crate) hash_R: [u8; HASH_METADATA_LEN_BYTES], - pub(crate) hash_t: [u8; HASH_METADATA_LEN_BYTES], - pub(crate) hash_w: [u8; HASH_METADATA_LEN_BYTES], - pub(crate) hash_agg: [u8; HASH_METADATA_LEN_BYTES], - pub(crate) hash_lmap: [u8; HASH_METADATA_LEN_BYTES], - pub(crate) hash_phi: [u8; HASH_METADATA_LEN_BYTES], - pub(crate) hash_xi: [u8; HASH_METADATA_LEN_BYTES], - pub(crate) hash_z: [u8; HASH_METADATA_LEN_BYTES], - pub(crate) hash_chi: [u8; HASH_METADATA_LEN_BYTES], + pub(crate) sid: Sid, + pub(crate) domain_separators: PKEv2DomainSeparators, +} + +#[derive(Clone, Debug)] +pub(crate) enum PKEv2DomainSeparators { + Legacy(Box), + Short(ShortPKEv2DomainSeparators), +} + +impl PKEv2DomainSeparators { + pub(crate) fn new(rng: &mut dyn RngCore) -> Self { + let ds = ShortPKEv2DomainSeparators { + hash: core::array::from_fn(|_| rng.gen()), + hash_R: core::array::from_fn(|_| rng.gen()), + hash_t: core::array::from_fn(|_| rng.gen()), + hash_w: core::array::from_fn(|_| rng.gen()), + hash_agg: core::array::from_fn(|_| rng.gen()), + hash_lmap: core::array::from_fn(|_| rng.gen()), + hash_phi: core::array::from_fn(|_| rng.gen()), + hash_xi: core::array::from_fn(|_| rng.gen()), + hash_z: core::array::from_fn(|_| rng.gen()), + hash_chi: core::array::from_fn(|_| rng.gen()), + }; + + Self::Short(ds) + } + + pub(crate) fn hash(&self) -> &[u8] { + match self { + PKEv2DomainSeparators::Legacy(ds) => &ds.hash, + PKEv2DomainSeparators::Short(ds) => &ds.hash, + } + } + + pub(crate) fn hash_R(&self) -> &[u8] { + match self { + PKEv2DomainSeparators::Legacy(ds) => &ds.hash_R, + PKEv2DomainSeparators::Short(ds) => &ds.hash_R, + } + } + + pub(crate) fn hash_t(&self) -> &[u8] { + match self { + PKEv2DomainSeparators::Legacy(ds) => &ds.hash_t, + PKEv2DomainSeparators::Short(ds) => &ds.hash_t, + } + } + + pub(crate) fn hash_w(&self) -> &[u8] { + match self { + PKEv2DomainSeparators::Legacy(ds) => &ds.hash_w, + PKEv2DomainSeparators::Short(ds) => &ds.hash_w, + } + } + + pub(crate) fn hash_agg(&self) -> &[u8] { + match self { + PKEv2DomainSeparators::Legacy(ds) => &ds.hash_agg, + PKEv2DomainSeparators::Short(ds) => &ds.hash_agg, + } + } + + pub(crate) fn hash_lmap(&self) -> &[u8] { + match self { + PKEv2DomainSeparators::Legacy(ds) => &ds.hash_lmap, + PKEv2DomainSeparators::Short(ds) => &ds.hash_lmap, + } + } + + pub(crate) fn hash_phi(&self) -> &[u8] { + match self { + PKEv2DomainSeparators::Legacy(ds) => &ds.hash_phi, + PKEv2DomainSeparators::Short(ds) => &ds.hash_phi, + } + } + + pub(crate) fn hash_xi(&self) -> &[u8] { + match self { + PKEv2DomainSeparators::Legacy(ds) => &ds.hash_xi, + PKEv2DomainSeparators::Short(ds) => &ds.hash_xi, + } + } + + pub(crate) fn hash_z(&self) -> &[u8] { + match self { + PKEv2DomainSeparators::Legacy(ds) => &ds.hash_z, + PKEv2DomainSeparators::Short(ds) => &ds.hash_z, + } + } + + pub(crate) fn hash_chi(&self) -> &[u8] { + match self { + PKEv2DomainSeparators::Legacy(ds) => &ds.hash_chi, + PKEv2DomainSeparators::Short(ds) => &ds.hash_chi, + } + } +} + +#[derive(Clone, Debug)] +pub struct LegacyPKEv2DomainSeparators { + pub(crate) hash: [u8; LEGACY_HASH_DS_LEN_BYTES], + pub(crate) hash_R: [u8; LEGACY_HASH_DS_LEN_BYTES], + pub(crate) hash_t: [u8; LEGACY_HASH_DS_LEN_BYTES], + pub(crate) hash_w: [u8; LEGACY_HASH_DS_LEN_BYTES], + pub(crate) hash_agg: [u8; LEGACY_HASH_DS_LEN_BYTES], + pub(crate) hash_lmap: [u8; LEGACY_HASH_DS_LEN_BYTES], + pub(crate) hash_phi: [u8; LEGACY_HASH_DS_LEN_BYTES], + pub(crate) hash_xi: [u8; LEGACY_HASH_DS_LEN_BYTES], + pub(crate) hash_z: [u8; LEGACY_HASH_DS_LEN_BYTES], + pub(crate) hash_chi: [u8; LEGACY_HASH_DS_LEN_BYTES], +} + +#[derive(Clone, Debug)] +pub struct ShortPKEv2DomainSeparators { + pub(crate) hash: [u8; HASH_DS_LEN_BYTES], + pub(crate) hash_R: [u8; HASH_DS_LEN_BYTES], + pub(crate) hash_t: [u8; HASH_DS_LEN_BYTES], + pub(crate) hash_w: [u8; HASH_DS_LEN_BYTES], + pub(crate) hash_agg: [u8; HASH_DS_LEN_BYTES], + pub(crate) hash_lmap: [u8; HASH_DS_LEN_BYTES], + pub(crate) hash_phi: [u8; HASH_DS_LEN_BYTES], + pub(crate) hash_xi: [u8; HASH_DS_LEN_BYTES], + pub(crate) hash_z: [u8; HASH_DS_LEN_BYTES], + pub(crate) hash_chi: [u8; HASH_DS_LEN_BYTES], } impl Compressible for PublicParams @@ -79,16 +194,8 @@ where t, msbs_zero_padding_bit_count, bound_type, - hash, - hash_R, - hash_t, - hash_w, - hash_agg, - hash_lmap, - hash_phi, - hash_xi, - hash_z, - hash_chi, + sid, + domain_separators, } = self; SerializablePKEv2PublicParams { g_lists: g_lists.compress(), @@ -102,16 +209,8 @@ where t: *t, msbs_zero_padding_bit_count: *msbs_zero_padding_bit_count, bound_type: *bound_type, - hash: hash.to_vec(), - hash_R: hash_R.to_vec(), - hash_t: hash_t.to_vec(), - hash_w: hash_w.to_vec(), - hash_agg: hash_agg.to_vec(), - hash_lmap: hash_lmap.to_vec(), - hash_phi: hash_phi.to_vec(), - hash_xi: hash_xi.to_vec(), - hash_z: hash_z.to_vec(), - hash_chi: hash_chi.to_vec(), + sid: sid.0, + domain_separators: domain_separators.clone().into(), } } @@ -128,16 +227,8 @@ where t, msbs_zero_padding_bit_count, bound_type, - hash, - hash_R, - hash_t, - hash_w, - hash_agg, - hash_lmap, - hash_phi, - hash_xi, - hash_z, - hash_chi, + sid, + domain_separators, } = compressed; let uncompressed_g_lists = GroupElements::uncompress(g_lists)?; @@ -159,16 +250,8 @@ where t, msbs_zero_padding_bit_count, bound_type, - hash: try_vec_to_array(hash)?, - hash_R: try_vec_to_array(hash_R)?, - hash_t: try_vec_to_array(hash_t)?, - hash_w: try_vec_to_array(hash_w)?, - hash_agg: try_vec_to_array(hash_agg)?, - hash_lmap: try_vec_to_array(hash_lmap)?, - hash_phi: try_vec_to_array(hash_phi)?, - hash_xi: try_vec_to_array(hash_xi)?, - hash_z: try_vec_to_array(hash_z)?, - hash_chi: try_vec_to_array(hash_chi)?, + sid: Sid(sid), + domain_separators: domain_separators.try_into()?, }) } } @@ -187,16 +270,17 @@ impl PublicParams { t: u64, msbs_zero_padding_bit_count: u64, bound_type: Bound, - hash: [u8; HASH_METADATA_LEN_BYTES], - hash_R: [u8; HASH_METADATA_LEN_BYTES], - hash_t: [u8; HASH_METADATA_LEN_BYTES], - hash_w: [u8; HASH_METADATA_LEN_BYTES], - hash_agg: [u8; HASH_METADATA_LEN_BYTES], - hash_lmap: [u8; HASH_METADATA_LEN_BYTES], - hash_phi: [u8; HASH_METADATA_LEN_BYTES], - hash_xi: [u8; HASH_METADATA_LEN_BYTES], - hash_z: [u8; HASH_METADATA_LEN_BYTES], - hash_chi: [u8; HASH_METADATA_LEN_BYTES], + sid: u128, + hash: [u8; HASH_DS_LEN_BYTES], + hash_R: [u8; HASH_DS_LEN_BYTES], + hash_t: [u8; HASH_DS_LEN_BYTES], + hash_w: [u8; HASH_DS_LEN_BYTES], + hash_agg: [u8; HASH_DS_LEN_BYTES], + hash_lmap: [u8; HASH_DS_LEN_BYTES], + hash_phi: [u8; HASH_DS_LEN_BYTES], + hash_xi: [u8; HASH_DS_LEN_BYTES], + hash_z: [u8; HASH_DS_LEN_BYTES], + hash_chi: [u8; HASH_DS_LEN_BYTES], ) -> Self { let B_squared = inf_norm_bound_to_euclidean_squared(B_inf, d + k); let (n, D, B_bound_squared, _) = @@ -213,16 +297,19 @@ impl PublicParams { t, msbs_zero_padding_bit_count, bound_type, - hash, - hash_R, - hash_t, - hash_w, - hash_agg, - hash_lmap, - hash_phi, - hash_xi, - hash_z, - hash_chi, + sid: Sid(Some(sid)), + domain_separators: PKEv2DomainSeparators::Short(ShortPKEv2DomainSeparators { + hash, + hash_R, + hash_t, + hash_w, + hash_agg, + hash_lmap, + hash_phi, + hash_xi, + hash_z, + hash_chi, + }), } } @@ -596,16 +683,8 @@ pub fn crs_gen_ghl( t, msbs_zero_padding_bit_count, bound_type, - hash: core::array::from_fn(|_| rng.gen()), - hash_R: core::array::from_fn(|_| rng.gen()), - hash_t: core::array::from_fn(|_| rng.gen()), - hash_w: core::array::from_fn(|_| rng.gen()), - hash_agg: core::array::from_fn(|_| rng.gen()), - hash_lmap: core::array::from_fn(|_| rng.gen()), - hash_phi: core::array::from_fn(|_| rng.gen()), - hash_xi: core::array::from_fn(|_| rng.gen()), - hash_z: core::array::from_fn(|_| rng.gen()), - hash_chi: core::array::from_fn(|_| rng.gen()), + sid: Sid::new(rng), + domain_separators: PKEv2DomainSeparators::new(rng), } } @@ -637,16 +716,8 @@ pub fn crs_gen_cs( t, msbs_zero_padding_bit_count, bound_type, - hash: core::array::from_fn(|_| rng.gen()), - hash_R: core::array::from_fn(|_| rng.gen()), - hash_t: core::array::from_fn(|_| rng.gen()), - hash_w: core::array::from_fn(|_| rng.gen()), - hash_agg: core::array::from_fn(|_| rng.gen()), - hash_lmap: core::array::from_fn(|_| rng.gen()), - hash_phi: core::array::from_fn(|_| rng.gen()), - hash_xi: core::array::from_fn(|_| rng.gen()), - hash_z: core::array::from_fn(|_| rng.gen()), - hash_chi: core::array::from_fn(|_| rng.gen()), + sid: Sid::new(rng), + domain_separators: PKEv2DomainSeparators::new(rng), } } @@ -739,16 +810,8 @@ fn prove_impl( t: t_input, msbs_zero_padding_bit_count, bound_type, - ref hash, - ref hash_R, - ref hash_t, - ref hash_w, - ref hash_agg, - ref hash_lmap, - ref hash_phi, - ref hash_xi, - ref hash_z, - ref hash_chi, + sid, + domain_separators: ref ds, }, PublicCommit { a, b, c1, c2, .. }, ) = public; @@ -898,7 +961,8 @@ fn prove_impl( let mut hasher = sha3::Shake256::default(); for &data in &[ - hash_R, + ds.hash_R(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, C_hat_e.to_le_bytes().as_ref(), @@ -973,7 +1037,8 @@ fn prove_impl( G::Zp::hash( &mut phi, &[ - hash_phi, + ds.hash_phi(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, R_bytes, @@ -1013,7 +1078,8 @@ fn prove_impl( G::Zp::hash( &mut xi, &[ - hash_xi, + ds.hash_xi(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, C_hat_e.to_le_bytes().as_ref(), @@ -1035,7 +1101,8 @@ fn prove_impl( G::Zp::hash( &mut y, &[ - hash, + ds.hash(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, R_bytes, @@ -1069,7 +1136,8 @@ fn prove_impl( G::Zp::hash_128bit( &mut t, &[ - hash_t, + ds.hash_t(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, y_bytes, @@ -1093,7 +1161,8 @@ fn prove_impl( G::Zp::hash( &mut theta, &[ - hash_lmap, + ds.hash_lmap(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, y_bytes, @@ -1128,7 +1197,8 @@ fn prove_impl( G::Zp::hash_128bit( &mut w, &[ - hash_w, + ds.hash_w(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, y_bytes, @@ -1154,7 +1224,8 @@ fn prove_impl( G::Zp::hash( &mut delta, &[ - hash_agg, + ds.hash_agg(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, y_bytes, @@ -1536,7 +1607,8 @@ fn prove_impl( G::Zp::hash( core::slice::from_mut(&mut z), &[ - hash_z, + ds.hash_z(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, y_bytes, @@ -1669,7 +1741,8 @@ fn prove_impl( G::Zp::hash( core::slice::from_mut(&mut chi), &[ - hash_chi, + ds.hash_chi(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, y_bytes, @@ -1886,16 +1959,8 @@ pub fn verify_inner( t: t_input, msbs_zero_padding_bit_count, bound_type, - ref hash, - ref hash_R, - ref hash_t, - ref hash_w, - ref hash_agg, - ref hash_lmap, - ref hash_phi, - ref hash_xi, - ref hash_z, - ref hash_chi, + sid, + domain_separators: ref ds, } = public.0; let g_list = &*g_lists.g_list.0; let g_hat_list = &*g_lists.g_hat_list.0; @@ -1976,7 +2041,8 @@ pub fn verify_inner( let mut hasher = sha3::Shake256::default(); for &data in &[ - hash_R, + ds.hash_R(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, C_hat_e.to_le_bytes().as_ref(), @@ -2013,7 +2079,8 @@ pub fn verify_inner( G::Zp::hash( &mut phi, &[ - hash_phi, + ds.hash_phi(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, R_bytes, @@ -2032,7 +2099,8 @@ pub fn verify_inner( G::Zp::hash( &mut xi, &[ - hash_xi, + ds.hash_xi(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, C_hat_e.to_le_bytes().as_ref(), @@ -2053,7 +2121,8 @@ pub fn verify_inner( G::Zp::hash( &mut y, &[ - hash, + ds.hash(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, R_bytes, @@ -2075,7 +2144,8 @@ pub fn verify_inner( G::Zp::hash_128bit( &mut t, &[ - hash_t, + ds.hash_t(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, y_bytes, @@ -2099,7 +2169,8 @@ pub fn verify_inner( G::Zp::hash( &mut theta, &[ - hash_lmap, + ds.hash_lmap(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, y_bytes, @@ -2124,7 +2195,8 @@ pub fn verify_inner( G::Zp::hash_128bit( &mut w, &[ - hash_w, + ds.hash_w(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, y_bytes, @@ -2160,7 +2232,8 @@ pub fn verify_inner( G::Zp::hash( &mut delta, &[ - hash_agg, + ds.hash_agg(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, y_bytes, @@ -2259,7 +2332,8 @@ pub fn verify_inner( G::Zp::hash( core::slice::from_mut(&mut z), &[ - hash_z, + ds.hash_z(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, y_bytes, @@ -2398,7 +2472,8 @@ pub fn verify_inner( G::Zp::hash( core::slice::from_mut(&mut chi), &[ - hash_chi, + ds.hash_chi(), + sid.to_le_bytes().as_slice(), metadata, x_bytes, y_bytes, diff --git a/tfhe-zk-pok/src/proofs/range.rs b/tfhe-zk-pok/src/proofs/range.rs index ba6b67283..8847d1f82 100644 --- a/tfhe-zk-pok/src/proofs/range.rs +++ b/tfhe-zk-pok/src/proofs/range.rs @@ -3,20 +3,20 @@ use super::*; #[derive(Clone, Debug)] pub struct PublicParams { g_lists: GroupElements, - hash: [u8; HASH_METADATA_LEN_BYTES], - hash_s: [u8; HASH_METADATA_LEN_BYTES], - hash_t: [u8; HASH_METADATA_LEN_BYTES], - hash_agg: [u8; HASH_METADATA_LEN_BYTES], + hash: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_s: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_t: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_agg: [u8; LEGACY_HASH_DS_LEN_BYTES], } impl PublicParams { pub fn from_vec( g_list: Vec>, g_hat_list: Vec>, - hash: [u8; HASH_METADATA_LEN_BYTES], - hash_s: [u8; HASH_METADATA_LEN_BYTES], - hash_t: [u8; HASH_METADATA_LEN_BYTES], - hash_agg: [u8; HASH_METADATA_LEN_BYTES], + hash: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_s: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_t: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_agg: [u8; LEGACY_HASH_DS_LEN_BYTES], ) -> Self { Self { g_lists: GroupElements::from_vec(g_list, g_hat_list), diff --git a/tfhe-zk-pok/src/proofs/rlwe.rs b/tfhe-zk-pok/src/proofs/rlwe.rs index e74c6e84e..2295ce7dc 100644 --- a/tfhe-zk-pok/src/proofs/rlwe.rs +++ b/tfhe-zk-pok/src/proofs/rlwe.rs @@ -15,12 +15,12 @@ pub struct PublicParams { big_m: usize, b_i: u64, q: u64, - hash: [u8; HASH_METADATA_LEN_BYTES], - hash_t: [u8; HASH_METADATA_LEN_BYTES], - hash_agg: [u8; HASH_METADATA_LEN_BYTES], - hash_lmap: [u8; HASH_METADATA_LEN_BYTES], - hash_z: [u8; HASH_METADATA_LEN_BYTES], - hash_w: [u8; HASH_METADATA_LEN_BYTES], + hash: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_t: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_agg: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_lmap: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_z: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_w: [u8; LEGACY_HASH_DS_LEN_BYTES], } impl PublicParams { @@ -33,12 +33,12 @@ impl PublicParams { big_m: usize, b_i: u64, q: u64, - hash: [u8; HASH_METADATA_LEN_BYTES], - hash_t: [u8; HASH_METADATA_LEN_BYTES], - hash_agg: [u8; HASH_METADATA_LEN_BYTES], - hash_lmap: [u8; HASH_METADATA_LEN_BYTES], - hash_z: [u8; HASH_METADATA_LEN_BYTES], - hash_w: [u8; HASH_METADATA_LEN_BYTES], + hash: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_t: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_agg: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_lmap: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_z: [u8; LEGACY_HASH_DS_LEN_BYTES], + hash_w: [u8; LEGACY_HASH_DS_LEN_BYTES], ) -> Self { Self { g_lists: GroupElements::from_vec(g_list, g_hat_list), diff --git a/tfhe-zk-pok/src/serialization.rs b/tfhe-zk-pok/src/serialization.rs index 8322e4cda..cb2554e7f 100644 --- a/tfhe-zk-pok/src/serialization.rs +++ b/tfhe-zk-pok/src/serialization.rs @@ -6,7 +6,8 @@ use std::marker::PhantomData; use crate::backward_compatibility::{ SerializableAffineVersions, SerializableCubicExtFieldVersions, SerializableFpVersions, - SerializableGroupElementsVersions, SerializablePKEv1PublicParamsVersions, + SerializableGroupElementsVersions, SerializablePKEv1DomainSeparatorsVersions, + SerializablePKEv1PublicParamsVersions, SerializablePKEv2DomainSeparatorsVersions, SerializablePKEv2PublicParamsVersions, SerializableQuadExtFieldVersions, }; use ark_ec::short_weierstrass::{Affine, SWCurveConfig}; @@ -16,9 +17,15 @@ use serde::{Deserialize, Serialize}; use tfhe_versionable::Versionize; use crate::curve_api::{Curve, CurveGroupOps}; -use crate::proofs::pke::PublicParams as PKEv1PublicParams; -use crate::proofs::pke_v2::{Bound, PublicParams as PKEv2PublicParams}; -use crate::proofs::GroupElements; +use crate::proofs::pke::{ + LegacyPKEv1DomainSeparators, PKEv1DomainSeparators, PublicParams as PKEv1PublicParams, + ShortPKEv1DomainSeparators, +}; +use crate::proofs::pke_v2::{ + Bound, LegacyPKEv2DomainSeparators, PKEv2DomainSeparators, PublicParams as PKEv2PublicParams, + ShortPKEv2DomainSeparators, +}; +use crate::proofs::{GroupElements, Sid, HASH_DS_LEN_BYTES, LEGACY_HASH_DS_LEN_BYTES}; /// Error returned when a conversion from a vec to a fixed size array failed because the vec size is /// incorrect @@ -399,26 +406,17 @@ impl From for InvalidSerializedPublicParamsError { pub struct SerializablePKEv2PublicParams { pub(crate) g_lists: SerializableGroupElements, pub(crate) D: usize, - pub n: usize, - pub d: usize, - pub k: usize, - pub B_bound_squared: u128, - pub B_inf: u64, - pub q: u64, - pub t: u64, - pub msbs_zero_padding_bit_count: u64, - pub bound_type: Bound, - // We use Vec since serde does not support fixed size arrays of 256 elements - pub(crate) hash: Vec, - pub(crate) hash_R: Vec, - pub(crate) hash_t: Vec, - pub(crate) hash_w: Vec, - pub(crate) hash_agg: Vec, - pub(crate) hash_lmap: Vec, - pub(crate) hash_phi: Vec, - pub(crate) hash_xi: Vec, - pub(crate) hash_z: Vec, - pub(crate) hash_chi: Vec, + pub(crate) n: usize, + pub(crate) d: usize, + pub(crate) k: usize, + pub(crate) B_bound_squared: u128, + pub(crate) B_inf: u64, + pub(crate) q: u64, + pub(crate) t: u64, + pub(crate) msbs_zero_padding_bit_count: u64, + pub(crate) bound_type: Bound, + pub(crate) sid: Option, + pub(crate) domain_separators: SerializablePKEv2DomainSeparators, } impl From> for SerializablePKEv2PublicParams @@ -438,16 +436,8 @@ where t, msbs_zero_padding_bit_count, bound_type, - hash, - hash_R, - hash_t, - hash_w, - hash_agg, - hash_lmap, - hash_phi, - hash_xi, - hash_z, - hash_chi, + sid, + domain_separators, } = value; Self { g_lists: g_lists.into(), @@ -461,16 +451,8 @@ where t, msbs_zero_padding_bit_count, bound_type, - hash: hash.to_vec(), - hash_R: hash_R.to_vec(), - hash_t: hash_t.to_vec(), - hash_w: hash_w.to_vec(), - hash_agg: hash_agg.to_vec(), - hash_lmap: hash_lmap.to_vec(), - hash_phi: hash_phi.to_vec(), - hash_xi: hash_xi.to_vec(), - hash_z: hash_z.to_vec(), - hash_chi: hash_chi.to_vec(), + sid: sid.0, + domain_separators: domain_separators.into(), } } } @@ -495,16 +477,8 @@ where t, msbs_zero_padding_bit_count, bound_type, - hash, - hash_R, - hash_t, - hash_w, - hash_agg, - hash_lmap, - hash_phi, - hash_xi, - hash_z, - hash_chi, + sid, + domain_separators, } = value; Ok(Self { g_lists: g_lists.try_into()?, @@ -518,6 +492,63 @@ where t, msbs_zero_padding_bit_count, bound_type, + sid: Sid(sid), + domain_separators: domain_separators.try_into()?, + }) + } +} + +#[derive(serde::Serialize, serde::Deserialize, Versionize)] +#[versionize(SerializablePKEv2DomainSeparatorsVersions)] +pub struct SerializablePKEv2DomainSeparators { + // We use Vec since serde does not support fixed size arrays of 256 elements + pub(crate) hash: Vec, + pub(crate) hash_R: Vec, + pub(crate) hash_t: Vec, + pub(crate) hash_w: Vec, + pub(crate) hash_agg: Vec, + pub(crate) hash_lmap: Vec, + pub(crate) hash_phi: Vec, + pub(crate) hash_xi: Vec, + pub(crate) hash_z: Vec, + pub(crate) hash_chi: Vec, +} + +impl From for SerializablePKEv2DomainSeparators { + fn from(value: PKEv2DomainSeparators) -> Self { + Self { + hash: value.hash().to_vec(), + hash_R: value.hash_R().to_vec(), + hash_t: value.hash_t().to_vec(), + hash_w: value.hash_w().to_vec(), + hash_agg: value.hash_agg().to_vec(), + hash_lmap: value.hash_lmap().to_vec(), + hash_phi: value.hash_phi().to_vec(), + hash_xi: value.hash_xi().to_vec(), + hash_z: value.hash_z().to_vec(), + hash_chi: value.hash_chi().to_vec(), + } + } +} + +impl TryFrom for LegacyPKEv2DomainSeparators { + type Error = InvalidArraySizeError; + + fn try_from(value: SerializablePKEv2DomainSeparators) -> Result { + let SerializablePKEv2DomainSeparators { + hash, + hash_R, + hash_t, + hash_w, + hash_agg, + hash_lmap, + hash_phi, + hash_xi, + hash_z, + hash_chi, + } = value; + + Ok(Self { hash: try_vec_to_array(hash)?, hash_R: try_vec_to_array(hash_R)?, hash_t: try_vec_to_array(hash_t)?, @@ -532,26 +563,70 @@ where } } +impl TryFrom for ShortPKEv2DomainSeparators { + type Error = InvalidArraySizeError; + + fn try_from(value: SerializablePKEv2DomainSeparators) -> Result { + let SerializablePKEv2DomainSeparators { + hash, + hash_R, + hash_t, + hash_w, + hash_agg, + hash_lmap, + hash_phi, + hash_xi, + hash_z, + hash_chi, + } = value; + + Ok(Self { + hash: try_vec_to_array(hash)?, + hash_R: try_vec_to_array(hash_R)?, + hash_t: try_vec_to_array(hash_t)?, + hash_w: try_vec_to_array(hash_w)?, + hash_agg: try_vec_to_array(hash_agg)?, + hash_lmap: try_vec_to_array(hash_lmap)?, + hash_phi: try_vec_to_array(hash_phi)?, + hash_xi: try_vec_to_array(hash_xi)?, + hash_z: try_vec_to_array(hash_z)?, + hash_chi: try_vec_to_array(hash_chi)?, + }) + } +} + +impl TryFrom for PKEv2DomainSeparators { + type Error = InvalidArraySizeError; + + fn try_from(value: SerializablePKEv2DomainSeparators) -> Result { + let len = value.hash.len(); + + match len { + LEGACY_HASH_DS_LEN_BYTES => Ok(Self::Legacy(Box::new(value.try_into()?))), + HASH_DS_LEN_BYTES => Ok(Self::Short(value.try_into()?)), + _ => Err(InvalidArraySizeError { + expected_len: HASH_DS_LEN_BYTES, + found_len: len, + }), + } + } +} + #[derive(serde::Serialize, serde::Deserialize, Versionize)] #[versionize(SerializablePKEv1PublicParamsVersions)] pub struct SerializablePKEv1PublicParams { pub(crate) g_lists: SerializableGroupElements, pub(crate) big_d: usize, - pub n: usize, - pub d: usize, - pub k: usize, - pub b: u64, - pub b_r: u64, - pub q: u64, - pub t: u64, - pub msbs_zero_padding_bit_count: u64, - // We use Vec since serde does not support fixed size arrays of 256 elements - pub(crate) hash: Vec, - pub(crate) hash_t: Vec, - pub(crate) hash_agg: Vec, - pub(crate) hash_lmap: Vec, - pub(crate) hash_z: Vec, - pub(crate) hash_w: Vec, + pub(crate) n: usize, + pub(crate) d: usize, + pub(crate) k: usize, + pub(crate) b: u64, + pub(crate) b_r: u64, + pub(crate) q: u64, + pub(crate) t: u64, + pub(crate) msbs_zero_padding_bit_count: u64, + pub(crate) sid: Option, + pub(crate) domain_separators: SerializablePKEv1DomainSeparators, } impl From> for SerializablePKEv1PublicParams @@ -570,12 +645,8 @@ where q, t, msbs_zero_padding_bit_count, - hash, - hash_t, - hash_agg, - hash_lmap, - hash_z, - hash_w, + sid, + domain_separators, } = value; Self { g_lists: g_lists.into(), @@ -588,12 +659,8 @@ where q, t, msbs_zero_padding_bit_count, - hash: hash.to_vec(), - hash_t: hash_t.to_vec(), - hash_agg: hash_agg.to_vec(), - hash_lmap: hash_lmap.to_vec(), - hash_z: hash_z.to_vec(), - hash_w: hash_w.to_vec(), + sid: sid.0, + domain_separators: domain_separators.into(), } } } @@ -617,12 +684,8 @@ where q, t, msbs_zero_padding_bit_count, - hash, - hash_t, - hash_agg, - hash_lmap, - hash_z, - hash_w, + sid, + domain_separators, } = value; Ok(Self { g_lists: g_lists.try_into()?, @@ -635,12 +698,98 @@ where q, t, msbs_zero_padding_bit_count, + sid: Sid(sid), + domain_separators: domain_separators.try_into()?, + }) + } +} + +#[derive(serde::Serialize, serde::Deserialize, Versionize)] +#[versionize(SerializablePKEv1DomainSeparatorsVersions)] +pub struct SerializablePKEv1DomainSeparators { + // We use Vec since serde does not support fixed size arrays of 256 elements + pub(crate) hash: Vec, + pub(crate) hash_t: Vec, + pub(crate) hash_agg: Vec, + pub(crate) hash_lmap: Vec, + pub(crate) hash_w: Vec, + pub(crate) hash_z: Vec, +} + +impl From for SerializablePKEv1DomainSeparators { + fn from(value: PKEv1DomainSeparators) -> Self { + Self { + hash: value.hash().to_vec(), + hash_t: value.hash_t().to_vec(), + hash_agg: value.hash_agg().to_vec(), + hash_lmap: value.hash_lmap().to_vec(), + hash_w: value.hash_w().to_vec(), + hash_z: value.hash_z().to_vec(), + } + } +} + +impl TryFrom for LegacyPKEv1DomainSeparators { + type Error = InvalidArraySizeError; + + fn try_from(value: SerializablePKEv1DomainSeparators) -> Result { + let SerializablePKEv1DomainSeparators { + hash, + hash_t, + hash_agg, + hash_lmap, + hash_w, + hash_z, + } = value; + + Ok(Self { hash: try_vec_to_array(hash)?, hash_t: try_vec_to_array(hash_t)?, hash_agg: try_vec_to_array(hash_agg)?, hash_lmap: try_vec_to_array(hash_lmap)?, - hash_z: try_vec_to_array(hash_z)?, hash_w: try_vec_to_array(hash_w)?, + hash_z: try_vec_to_array(hash_z)?, }) } } + +impl TryFrom for ShortPKEv1DomainSeparators { + type Error = InvalidArraySizeError; + + fn try_from(value: SerializablePKEv1DomainSeparators) -> Result { + let SerializablePKEv1DomainSeparators { + hash, + hash_t, + hash_agg, + hash_lmap, + hash_w, + hash_z, + } = value; + + Ok(Self { + hash: try_vec_to_array(hash)?, + hash_t: try_vec_to_array(hash_t)?, + hash_agg: try_vec_to_array(hash_agg)?, + hash_lmap: try_vec_to_array(hash_lmap)?, + hash_w: try_vec_to_array(hash_w)?, + hash_z: try_vec_to_array(hash_z)?, + }) + } +} + +impl TryFrom for PKEv1DomainSeparators { + type Error = InvalidArraySizeError; + + fn try_from(value: SerializablePKEv1DomainSeparators) -> Result { + let len = value.hash.len(); + + match len { + LEGACY_HASH_DS_LEN_BYTES => Ok(Self::Legacy(Box::new(value.try_into()?))), + HASH_DS_LEN_BYTES => Ok(Self::Short(value.try_into()?)), + _ => Err(InvalidArraySizeError { + expected_len: HASH_DS_LEN_BYTES, + found_len: len, + }), + } + } +} diff --git a/tfhe/src/zk/backward_compatibility.rs b/tfhe/src/zk/backward_compatibility.rs index a07dcaea4..28e51a62f 100644 --- a/tfhe/src/zk/backward_compatibility.rs +++ b/tfhe/src/zk/backward_compatibility.rs @@ -2,7 +2,7 @@ use std::convert::Infallible; use tfhe_versionable::{Upgrade, Version, VersionsDispatch}; use tfhe_zk_pok::backward_compatibility::pke::ProofV0; -use tfhe_zk_pok::backward_compatibility::IncompleteProof; +use tfhe_zk_pok::backward_compatibility::{IncompleteProof, SerializablePKEv1PublicParamsV0}; use tfhe_zk_pok::proofs::pke::Proof; use tfhe_zk_pok::serialization::InvalidSerializedPublicParamsError; @@ -14,13 +14,18 @@ use super::{ #[derive(Version)] #[repr(transparent)] -pub struct CompactPkeCrsV0(SerializableCompactPkePublicParams); +pub struct CompactPkeCrsV0(SerializablePKEv1PublicParamsV0); impl Upgrade for CompactPkeCrsV0 { type Error = InvalidSerializedPublicParamsError; fn upgrade(self) -> Result { - Ok(CompactPkeCrs::PkeV1(self.0.try_into()?)) + Ok(CompactPkeCrs::PkeV1( + self.0 + .upgrade() + .unwrap() // update is infallible so it is ok to unwrap + .try_into()?, + )) } }