mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-07 22:04:10 -05:00
chore(zk): refactor hashes to reuse code between proof and verify
This commit is contained in:
committed by
Nicolas Sarlin
parent
58f7457660
commit
ce7c15585e
773
tfhe-zk-pok/src/proofs/pke_v2/hashes.rs
Normal file
773
tfhe-zk-pok/src/proofs/pke_v2/hashes.rs
Normal file
@@ -0,0 +1,773 @@
|
||||
/// Scalar generation using the hash random oracle
|
||||
use crate::{
|
||||
curve_api::{Curve, FieldOps},
|
||||
proofs::pke_v2::{compute_crs_params, inf_norm_bound_to_euclidean_squared},
|
||||
};
|
||||
|
||||
use super::{PKEv2DomainSeparators, PublicCommit, PublicParams};
|
||||
|
||||
// The scalar used for the proof are generated using sha3 as a random oracle. The inputs of the hash
|
||||
// that generates a given scalar are reused for the subsequent hashes. We use the typestate pattern
|
||||
// to propagate the inputs from one hash to the next.
|
||||
|
||||
struct RInputs<'a> {
|
||||
ds: &'a PKEv2DomainSeparators,
|
||||
sid_bytes: Box<[u8]>,
|
||||
metadata: &'a [u8],
|
||||
x_bytes: Box<[u8]>,
|
||||
C_hat_e_bytes: &'a [u8],
|
||||
C_e_bytes: &'a [u8],
|
||||
C_r_tilde_bytes: &'a [u8],
|
||||
D: usize,
|
||||
m: usize,
|
||||
n: usize,
|
||||
k: usize,
|
||||
d: usize,
|
||||
}
|
||||
|
||||
pub(super) struct RHash<'a> {
|
||||
R_inputs: RInputs<'a>,
|
||||
R_bytes: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl<'a> RHash<'a> {
|
||||
pub(super) fn new<G: Curve>(
|
||||
public: (&'a PublicParams<G>, &PublicCommit<G>),
|
||||
metadata: &'a [u8],
|
||||
C_hat_e_bytes: &'a [u8],
|
||||
C_e_bytes: &'a [u8],
|
||||
C_r_tilde_bytes: &'a [u8],
|
||||
) -> (Box<[i8]>, Self) {
|
||||
let (
|
||||
&PublicParams {
|
||||
g_lists: _,
|
||||
D: _,
|
||||
n,
|
||||
d,
|
||||
k: _,
|
||||
B_bound_squared: _,
|
||||
B_inf,
|
||||
q,
|
||||
t: t_input,
|
||||
msbs_zero_padding_bit_count,
|
||||
bound_type,
|
||||
sid,
|
||||
domain_separators: ref ds,
|
||||
},
|
||||
PublicCommit { a, b, c1, c2, .. },
|
||||
) = public;
|
||||
|
||||
let k = c2.len();
|
||||
let B_squared = inf_norm_bound_to_euclidean_squared(B_inf, d + k);
|
||||
let (_, D, _, m) = compute_crs_params(
|
||||
d,
|
||||
k,
|
||||
B_squared,
|
||||
t_input,
|
||||
msbs_zero_padding_bit_count,
|
||||
bound_type,
|
||||
);
|
||||
|
||||
let x_bytes = [
|
||||
q.to_le_bytes().as_slice(),
|
||||
(d as u64).to_le_bytes().as_slice(),
|
||||
B_squared.to_le_bytes().as_slice(),
|
||||
t_input.to_le_bytes().as_slice(),
|
||||
msbs_zero_padding_bit_count.to_le_bytes().as_slice(),
|
||||
&*a.iter()
|
||||
.flat_map(|&x| x.to_le_bytes())
|
||||
.collect::<Box<[_]>>(),
|
||||
&*b.iter()
|
||||
.flat_map(|&x| x.to_le_bytes())
|
||||
.collect::<Box<[_]>>(),
|
||||
&*c1.iter()
|
||||
.flat_map(|&x| x.to_le_bytes())
|
||||
.collect::<Box<[_]>>(),
|
||||
&*c2.iter()
|
||||
.flat_map(|&x| x.to_le_bytes())
|
||||
.collect::<Box<[_]>>(),
|
||||
]
|
||||
.iter()
|
||||
.copied()
|
||||
.flatten()
|
||||
.copied()
|
||||
.collect::<Box<[_]>>();
|
||||
|
||||
let sid_bytes = Box::from(sid.to_le_bytes().as_slice());
|
||||
|
||||
// make R_bar a random number generator from the given bytes
|
||||
use sha3::digest::{ExtendableOutput, Update, XofReader};
|
||||
|
||||
let mut hasher = sha3::Shake256::default();
|
||||
for &data in &[
|
||||
ds.hash_R(),
|
||||
&sid_bytes,
|
||||
metadata,
|
||||
&x_bytes,
|
||||
C_hat_e_bytes,
|
||||
C_e_bytes,
|
||||
C_r_tilde_bytes,
|
||||
] {
|
||||
hasher.update(data);
|
||||
}
|
||||
let mut R_bar = hasher.finalize_xof();
|
||||
let R = (0..128 * (2 * (d + k) + 4))
|
||||
.map(|_| {
|
||||
let mut byte = 0u8;
|
||||
R_bar.read(core::slice::from_mut(&mut byte));
|
||||
|
||||
// take two bits
|
||||
match byte & 0b11 {
|
||||
// probability 1/2
|
||||
0 | 1 => 0,
|
||||
// probability 1/4
|
||||
2 => 1,
|
||||
// probability 1/4
|
||||
3 => -1,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
})
|
||||
.collect::<Box<[i8]>>();
|
||||
|
||||
let R_coeffs = |i: usize, j: usize| R[i + j * 128];
|
||||
let R_bytes = (0..128)
|
||||
.flat_map(|i| (0..(2 * (d + k) + 4)).map(move |j| R_coeffs(i, j) as u8))
|
||||
.collect();
|
||||
|
||||
(
|
||||
R,
|
||||
Self {
|
||||
R_inputs: RInputs {
|
||||
ds,
|
||||
sid_bytes,
|
||||
metadata,
|
||||
x_bytes,
|
||||
C_hat_e_bytes,
|
||||
C_e_bytes,
|
||||
C_r_tilde_bytes,
|
||||
D,
|
||||
m,
|
||||
n,
|
||||
k,
|
||||
d,
|
||||
},
|
||||
|
||||
R_bytes,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub(super) fn gen_phi<Zp: FieldOps>(self, C_R_bytes: &'a [u8]) -> ([Zp; 128], PhiHash<'a>) {
|
||||
let Self { R_inputs, R_bytes } = self;
|
||||
|
||||
let mut phi = [Zp::ZERO; 128];
|
||||
Zp::hash(
|
||||
&mut phi,
|
||||
&[
|
||||
R_inputs.ds.hash_phi(),
|
||||
&R_inputs.sid_bytes,
|
||||
R_inputs.metadata,
|
||||
&R_inputs.x_bytes,
|
||||
&R_bytes,
|
||||
R_inputs.C_hat_e_bytes,
|
||||
R_inputs.C_e_bytes,
|
||||
C_R_bytes,
|
||||
R_inputs.C_r_tilde_bytes,
|
||||
],
|
||||
);
|
||||
let phi_bytes = phi
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
|
||||
(
|
||||
phi,
|
||||
PhiHash {
|
||||
R_inputs,
|
||||
phi_inputs: PhiInputs { C_R_bytes },
|
||||
R_bytes,
|
||||
phi_bytes,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct PhiInputs<'a> {
|
||||
C_R_bytes: &'a [u8],
|
||||
}
|
||||
|
||||
pub(super) struct PhiHash<'a> {
|
||||
R_inputs: RInputs<'a>,
|
||||
R_bytes: Box<[u8]>,
|
||||
phi_inputs: PhiInputs<'a>,
|
||||
phi_bytes: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl<'a> PhiHash<'a> {
|
||||
pub(super) fn gen_xi<Zp: FieldOps>(self, C_hat_bin_bytes: &'a [u8]) -> ([Zp; 128], XiHash<'a>) {
|
||||
let Self {
|
||||
R_inputs,
|
||||
R_bytes,
|
||||
phi_inputs,
|
||||
phi_bytes,
|
||||
} = self;
|
||||
|
||||
let mut xi = [Zp::ZERO; 128];
|
||||
Zp::hash(
|
||||
&mut xi,
|
||||
&[
|
||||
R_inputs.ds.hash_xi(),
|
||||
&R_inputs.sid_bytes,
|
||||
R_inputs.metadata,
|
||||
&R_inputs.x_bytes,
|
||||
R_inputs.C_hat_e_bytes,
|
||||
R_inputs.C_e_bytes,
|
||||
&R_bytes,
|
||||
&phi_bytes,
|
||||
phi_inputs.C_R_bytes,
|
||||
C_hat_bin_bytes,
|
||||
R_inputs.C_r_tilde_bytes,
|
||||
],
|
||||
);
|
||||
|
||||
let xi_bytes = xi
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
|
||||
(
|
||||
xi,
|
||||
XiHash {
|
||||
R_inputs,
|
||||
R_bytes,
|
||||
phi_inputs,
|
||||
phi_bytes,
|
||||
xi_inputs: XiInputs { C_hat_bin_bytes },
|
||||
xi_bytes,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct XiInputs<'a> {
|
||||
C_hat_bin_bytes: &'a [u8],
|
||||
}
|
||||
|
||||
pub(super) struct XiHash<'a> {
|
||||
R_inputs: RInputs<'a>,
|
||||
R_bytes: Box<[u8]>,
|
||||
phi_inputs: PhiInputs<'a>,
|
||||
phi_bytes: Box<[u8]>,
|
||||
xi_inputs: XiInputs<'a>,
|
||||
xi_bytes: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl<'a> XiHash<'a> {
|
||||
pub(super) fn gen_y<Zp: FieldOps>(self) -> (Vec<Zp>, YHash<'a>) {
|
||||
let Self {
|
||||
R_inputs,
|
||||
R_bytes,
|
||||
phi_inputs,
|
||||
phi_bytes,
|
||||
xi_inputs,
|
||||
xi_bytes,
|
||||
} = self;
|
||||
|
||||
let mut y = vec![Zp::ZERO; R_inputs.D + 128 * R_inputs.m];
|
||||
Zp::hash(
|
||||
&mut y,
|
||||
&[
|
||||
R_inputs.ds.hash(),
|
||||
&R_inputs.sid_bytes,
|
||||
R_inputs.metadata,
|
||||
&R_inputs.x_bytes,
|
||||
&R_bytes,
|
||||
&phi_bytes,
|
||||
&xi_bytes,
|
||||
R_inputs.C_hat_e_bytes,
|
||||
R_inputs.C_e_bytes,
|
||||
phi_inputs.C_R_bytes,
|
||||
xi_inputs.C_hat_bin_bytes,
|
||||
R_inputs.C_r_tilde_bytes,
|
||||
],
|
||||
);
|
||||
let y_bytes = y
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
|
||||
(
|
||||
y,
|
||||
YHash {
|
||||
R_inputs,
|
||||
R_bytes,
|
||||
phi_inputs,
|
||||
phi_bytes,
|
||||
xi_inputs,
|
||||
xi_bytes,
|
||||
y_bytes,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct YHash<'a> {
|
||||
R_inputs: RInputs<'a>,
|
||||
R_bytes: Box<[u8]>,
|
||||
phi_inputs: PhiInputs<'a>,
|
||||
phi_bytes: Box<[u8]>,
|
||||
xi_inputs: XiInputs<'a>,
|
||||
xi_bytes: Box<[u8]>,
|
||||
y_bytes: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl<'a> YHash<'a> {
|
||||
pub(super) fn gen_t<Zp: FieldOps>(self, C_y_bytes: &'a [u8]) -> (Vec<Zp>, THash<'a>) {
|
||||
let Self {
|
||||
R_inputs,
|
||||
R_bytes,
|
||||
phi_inputs,
|
||||
phi_bytes,
|
||||
xi_inputs,
|
||||
xi_bytes,
|
||||
y_bytes,
|
||||
} = self;
|
||||
|
||||
let mut t = vec![Zp::ZERO; R_inputs.n];
|
||||
Zp::hash_128bit(
|
||||
&mut t,
|
||||
&[
|
||||
R_inputs.ds.hash_t(),
|
||||
&R_inputs.sid_bytes,
|
||||
R_inputs.metadata,
|
||||
&R_inputs.x_bytes,
|
||||
&y_bytes,
|
||||
&phi_bytes,
|
||||
&xi_bytes,
|
||||
R_inputs.C_hat_e_bytes,
|
||||
R_inputs.C_e_bytes,
|
||||
&R_bytes,
|
||||
phi_inputs.C_R_bytes,
|
||||
xi_inputs.C_hat_bin_bytes,
|
||||
R_inputs.C_r_tilde_bytes,
|
||||
C_y_bytes,
|
||||
],
|
||||
);
|
||||
let t_bytes = t
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
|
||||
(
|
||||
t,
|
||||
THash {
|
||||
R_inputs,
|
||||
R_bytes,
|
||||
phi_inputs,
|
||||
phi_bytes,
|
||||
xi_inputs,
|
||||
xi_bytes,
|
||||
y_bytes,
|
||||
t_inputs: TInputs { C_y_bytes },
|
||||
t_bytes,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct TInputs<'a> {
|
||||
C_y_bytes: &'a [u8],
|
||||
}
|
||||
|
||||
pub(super) struct THash<'a> {
|
||||
R_inputs: RInputs<'a>,
|
||||
R_bytes: Box<[u8]>,
|
||||
phi_inputs: PhiInputs<'a>,
|
||||
phi_bytes: Box<[u8]>,
|
||||
xi_inputs: XiInputs<'a>,
|
||||
xi_bytes: Box<[u8]>,
|
||||
y_bytes: Box<[u8]>,
|
||||
t_inputs: TInputs<'a>,
|
||||
t_bytes: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl<'a> THash<'a> {
|
||||
pub(super) fn gen_theta<Zp: FieldOps>(self) -> (Vec<Zp>, ThetaHash<'a>) {
|
||||
let Self {
|
||||
R_inputs,
|
||||
phi_inputs,
|
||||
xi_inputs,
|
||||
t_inputs,
|
||||
t_bytes,
|
||||
R_bytes,
|
||||
phi_bytes,
|
||||
xi_bytes,
|
||||
y_bytes,
|
||||
} = self;
|
||||
|
||||
let mut theta = vec![Zp::ZERO; R_inputs.d + R_inputs.k];
|
||||
Zp::hash(
|
||||
&mut theta,
|
||||
&[
|
||||
R_inputs.ds.hash_lmap(),
|
||||
&R_inputs.sid_bytes,
|
||||
R_inputs.metadata,
|
||||
&R_inputs.x_bytes,
|
||||
&y_bytes,
|
||||
&t_bytes,
|
||||
&phi_bytes,
|
||||
&xi_bytes,
|
||||
R_inputs.C_hat_e_bytes,
|
||||
R_inputs.C_e_bytes,
|
||||
&R_bytes,
|
||||
phi_inputs.C_R_bytes,
|
||||
xi_inputs.C_hat_bin_bytes,
|
||||
R_inputs.C_r_tilde_bytes,
|
||||
t_inputs.C_y_bytes,
|
||||
],
|
||||
);
|
||||
let theta_bytes = theta
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
|
||||
(
|
||||
theta,
|
||||
ThetaHash {
|
||||
R_inputs,
|
||||
R_bytes,
|
||||
phi_inputs,
|
||||
phi_bytes,
|
||||
xi_inputs,
|
||||
xi_bytes,
|
||||
y_bytes,
|
||||
t_inputs,
|
||||
t_bytes,
|
||||
theta_bytes,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct ThetaHash<'a> {
|
||||
R_inputs: RInputs<'a>,
|
||||
R_bytes: Box<[u8]>,
|
||||
phi_inputs: PhiInputs<'a>,
|
||||
phi_bytes: Box<[u8]>,
|
||||
xi_inputs: XiInputs<'a>,
|
||||
xi_bytes: Box<[u8]>,
|
||||
y_bytes: Box<[u8]>,
|
||||
t_inputs: TInputs<'a>,
|
||||
t_bytes: Box<[u8]>,
|
||||
theta_bytes: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl<'a> ThetaHash<'a> {
|
||||
pub(super) fn gen_omega<Zp: FieldOps>(self) -> (Vec<Zp>, OmegaHash<'a>) {
|
||||
let Self {
|
||||
R_inputs,
|
||||
R_bytes,
|
||||
phi_inputs,
|
||||
phi_bytes,
|
||||
xi_inputs,
|
||||
xi_bytes,
|
||||
y_bytes,
|
||||
t_inputs,
|
||||
t_bytes,
|
||||
theta_bytes,
|
||||
} = self;
|
||||
|
||||
let mut omega = vec![Zp::ZERO; R_inputs.n];
|
||||
Zp::hash_128bit(
|
||||
&mut omega,
|
||||
&[
|
||||
R_inputs.ds.hash_w(),
|
||||
&R_inputs.sid_bytes,
|
||||
R_inputs.metadata,
|
||||
&R_inputs.x_bytes,
|
||||
&y_bytes,
|
||||
&t_bytes,
|
||||
&phi_bytes,
|
||||
&xi_bytes,
|
||||
&theta_bytes,
|
||||
R_inputs.C_hat_e_bytes,
|
||||
R_inputs.C_e_bytes,
|
||||
&R_bytes,
|
||||
phi_inputs.C_R_bytes,
|
||||
xi_inputs.C_hat_bin_bytes,
|
||||
R_inputs.C_r_tilde_bytes,
|
||||
t_inputs.C_y_bytes,
|
||||
],
|
||||
);
|
||||
let omega_bytes = omega
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
|
||||
(
|
||||
omega,
|
||||
OmegaHash {
|
||||
R_inputs,
|
||||
R_bytes,
|
||||
phi_inputs,
|
||||
phi_bytes,
|
||||
xi_inputs,
|
||||
xi_bytes,
|
||||
y_bytes,
|
||||
t_inputs,
|
||||
t_bytes,
|
||||
theta_bytes,
|
||||
omega_bytes,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct OmegaHash<'a> {
|
||||
R_inputs: RInputs<'a>,
|
||||
R_bytes: Box<[u8]>,
|
||||
phi_inputs: PhiInputs<'a>,
|
||||
phi_bytes: Box<[u8]>,
|
||||
xi_inputs: XiInputs<'a>,
|
||||
xi_bytes: Box<[u8]>,
|
||||
y_bytes: Box<[u8]>,
|
||||
t_inputs: TInputs<'a>,
|
||||
t_bytes: Box<[u8]>,
|
||||
theta_bytes: Box<[u8]>,
|
||||
omega_bytes: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl<'a> OmegaHash<'a> {
|
||||
pub(super) fn gen_delta<Zp: FieldOps>(self) -> ([Zp; 7], DeltaHash<'a>) {
|
||||
let Self {
|
||||
R_inputs,
|
||||
R_bytes,
|
||||
phi_inputs,
|
||||
phi_bytes,
|
||||
xi_inputs,
|
||||
xi_bytes,
|
||||
y_bytes,
|
||||
t_inputs,
|
||||
t_bytes,
|
||||
theta_bytes,
|
||||
omega_bytes,
|
||||
} = self;
|
||||
|
||||
let mut delta = [Zp::ZERO; 7];
|
||||
Zp::hash(
|
||||
&mut delta,
|
||||
&[
|
||||
R_inputs.ds.hash_agg(),
|
||||
&R_inputs.sid_bytes,
|
||||
R_inputs.metadata,
|
||||
&R_inputs.x_bytes,
|
||||
&y_bytes,
|
||||
&t_bytes,
|
||||
&phi_bytes,
|
||||
&xi_bytes,
|
||||
&theta_bytes,
|
||||
&omega_bytes,
|
||||
R_inputs.C_hat_e_bytes,
|
||||
R_inputs.C_e_bytes,
|
||||
&R_bytes,
|
||||
phi_inputs.C_R_bytes,
|
||||
xi_inputs.C_hat_bin_bytes,
|
||||
R_inputs.C_r_tilde_bytes,
|
||||
t_inputs.C_y_bytes,
|
||||
],
|
||||
);
|
||||
let delta_bytes = delta
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
|
||||
(
|
||||
delta,
|
||||
DeltaHash {
|
||||
R_inputs,
|
||||
R_bytes,
|
||||
phi_inputs,
|
||||
phi_bytes,
|
||||
xi_inputs,
|
||||
xi_bytes,
|
||||
y_bytes,
|
||||
t_inputs,
|
||||
t_bytes,
|
||||
theta_bytes,
|
||||
delta_bytes,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct DeltaHash<'a> {
|
||||
R_inputs: RInputs<'a>,
|
||||
R_bytes: Box<[u8]>,
|
||||
phi_inputs: PhiInputs<'a>,
|
||||
phi_bytes: Box<[u8]>,
|
||||
xi_inputs: XiInputs<'a>,
|
||||
xi_bytes: Box<[u8]>,
|
||||
y_bytes: Box<[u8]>,
|
||||
t_inputs: TInputs<'a>,
|
||||
t_bytes: Box<[u8]>,
|
||||
theta_bytes: Box<[u8]>,
|
||||
delta_bytes: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl<'a> DeltaHash<'a> {
|
||||
pub(super) fn gen_z<Zp: FieldOps>(
|
||||
self,
|
||||
C_h1_bytes: &'a [u8],
|
||||
C_h2_bytes: &'a [u8],
|
||||
C_hat_t_bytes: &'a [u8],
|
||||
C_hat_h3_bytes: &'a [u8],
|
||||
C_hat_omega_bytes: &'a [u8],
|
||||
) -> (Zp, ZHash<'a>) {
|
||||
let Self {
|
||||
R_inputs,
|
||||
R_bytes,
|
||||
phi_inputs,
|
||||
phi_bytes,
|
||||
xi_inputs,
|
||||
xi_bytes,
|
||||
y_bytes,
|
||||
t_inputs,
|
||||
t_bytes,
|
||||
theta_bytes,
|
||||
delta_bytes,
|
||||
} = self;
|
||||
|
||||
let mut z = Zp::ZERO;
|
||||
Zp::hash(
|
||||
core::slice::from_mut(&mut z),
|
||||
&[
|
||||
R_inputs.ds.hash_z(),
|
||||
&R_inputs.sid_bytes,
|
||||
R_inputs.metadata,
|
||||
&R_inputs.x_bytes,
|
||||
&y_bytes,
|
||||
&t_bytes,
|
||||
&phi_bytes,
|
||||
&R_inputs.x_bytes, // x is duplicated but we have to keep it for backward compat
|
||||
&theta_bytes,
|
||||
&delta_bytes,
|
||||
R_inputs.C_hat_e_bytes,
|
||||
R_inputs.C_e_bytes,
|
||||
&R_bytes,
|
||||
phi_inputs.C_R_bytes,
|
||||
xi_inputs.C_hat_bin_bytes,
|
||||
R_inputs.C_r_tilde_bytes,
|
||||
t_inputs.C_y_bytes,
|
||||
C_h1_bytes,
|
||||
C_h2_bytes,
|
||||
C_hat_t_bytes,
|
||||
C_hat_h3_bytes,
|
||||
C_hat_omega_bytes,
|
||||
],
|
||||
);
|
||||
|
||||
(
|
||||
z,
|
||||
ZHash {
|
||||
R_inputs,
|
||||
R_bytes,
|
||||
phi_inputs,
|
||||
phi_bytes,
|
||||
xi_inputs,
|
||||
xi_bytes,
|
||||
y_bytes,
|
||||
t_inputs,
|
||||
t_bytes,
|
||||
theta_bytes,
|
||||
delta_bytes,
|
||||
z_inputs: ZInputs {
|
||||
C_h1_bytes,
|
||||
C_h2_bytes,
|
||||
C_hat_t_bytes,
|
||||
C_hat_h3_bytes,
|
||||
C_hat_omega_bytes,
|
||||
},
|
||||
z_bytes: Box::from(z.to_le_bytes().as_ref()),
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct ZInputs<'a> {
|
||||
C_h1_bytes: &'a [u8],
|
||||
C_h2_bytes: &'a [u8],
|
||||
C_hat_t_bytes: &'a [u8],
|
||||
C_hat_h3_bytes: &'a [u8],
|
||||
C_hat_omega_bytes: &'a [u8],
|
||||
}
|
||||
|
||||
pub(super) struct ZHash<'a> {
|
||||
R_inputs: RInputs<'a>,
|
||||
R_bytes: Box<[u8]>,
|
||||
phi_inputs: PhiInputs<'a>,
|
||||
phi_bytes: Box<[u8]>,
|
||||
xi_inputs: XiInputs<'a>,
|
||||
xi_bytes: Box<[u8]>,
|
||||
y_bytes: Box<[u8]>,
|
||||
t_inputs: TInputs<'a>,
|
||||
t_bytes: Box<[u8]>,
|
||||
theta_bytes: Box<[u8]>,
|
||||
delta_bytes: Box<[u8]>,
|
||||
z_inputs: ZInputs<'a>,
|
||||
z_bytes: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl<'a> ZHash<'a> {
|
||||
pub(super) fn gen_chi<Zp: FieldOps>(self, p_h1: Zp, p_h2: Zp, p_t: Zp) -> Zp {
|
||||
let Self {
|
||||
R_inputs,
|
||||
R_bytes,
|
||||
phi_inputs,
|
||||
phi_bytes,
|
||||
xi_inputs,
|
||||
xi_bytes,
|
||||
y_bytes,
|
||||
t_inputs,
|
||||
t_bytes,
|
||||
theta_bytes,
|
||||
delta_bytes,
|
||||
z_inputs,
|
||||
z_bytes,
|
||||
} = self;
|
||||
|
||||
let mut chi = Zp::ZERO;
|
||||
Zp::hash(
|
||||
core::slice::from_mut(&mut chi),
|
||||
&[
|
||||
R_inputs.ds.hash_chi(),
|
||||
&R_inputs.sid_bytes,
|
||||
R_inputs.metadata,
|
||||
&R_inputs.x_bytes,
|
||||
&y_bytes,
|
||||
&t_bytes,
|
||||
&phi_bytes,
|
||||
&xi_bytes,
|
||||
&theta_bytes,
|
||||
&delta_bytes,
|
||||
R_inputs.C_hat_e_bytes,
|
||||
R_inputs.C_e_bytes,
|
||||
&R_bytes,
|
||||
phi_inputs.C_R_bytes,
|
||||
xi_inputs.C_hat_bin_bytes,
|
||||
R_inputs.C_r_tilde_bytes,
|
||||
t_inputs.C_y_bytes,
|
||||
z_inputs.C_h1_bytes,
|
||||
z_inputs.C_h2_bytes,
|
||||
z_inputs.C_hat_t_bytes,
|
||||
z_inputs.C_hat_h3_bytes,
|
||||
z_inputs.C_hat_omega_bytes,
|
||||
&z_bytes,
|
||||
p_h1.to_le_bytes().as_ref(),
|
||||
p_h2.to_le_bytes().as_ref(),
|
||||
p_t.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
|
||||
chi
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,10 @@ use core::marker::PhantomData;
|
||||
use rayon::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
mod hashes;
|
||||
|
||||
use hashes::RHash;
|
||||
|
||||
fn bit_iter(x: u64, nbits: u32) -> impl Iterator<Item = bool> {
|
||||
(0..nbits).map(move |idx| ((x >> idx) & 1) != 0)
|
||||
}
|
||||
@@ -416,6 +420,19 @@ pub(crate) struct ComputeLoadProofFields<G: Curve> {
|
||||
pub(crate) C_hat_w: G::G2,
|
||||
}
|
||||
|
||||
impl<G: Curve> ComputeLoadProofFields<G> {
|
||||
fn to_le_bytes(fields: &Option<Self>) -> (Box<[u8]>, Box<[u8]>) {
|
||||
if let Some(ComputeLoadProofFields { C_hat_h3, C_hat_w }) = fields.as_ref() {
|
||||
(
|
||||
Box::from(G::G2::to_le_bytes(*C_hat_h3).as_ref()),
|
||||
Box::from(G::G2::to_le_bytes(*C_hat_w).as_ref()),
|
||||
)
|
||||
} else {
|
||||
(Box::from([]), Box::from([]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Versionize)]
|
||||
#[serde(bound(
|
||||
deserialize = "G: Curve, CompressedG1<G>: serde::Deserialize<'de>, CompressedG2<G>: serde::Deserialize<'de>",
|
||||
@@ -821,7 +838,7 @@ fn prove_impl<G: Curve>(
|
||||
t: t_input,
|
||||
msbs_zero_padding_bit_count,
|
||||
bound_type,
|
||||
sid,
|
||||
sid: _,
|
||||
domain_separators: ref ds,
|
||||
},
|
||||
PublicCommit { a, b, c1, c2, .. },
|
||||
@@ -939,69 +956,18 @@ fn prove_impl<G: Curve>(
|
||||
},
|
||||
);
|
||||
|
||||
let x_bytes = &*[
|
||||
q.to_le_bytes().as_slice(),
|
||||
(d as u64).to_le_bytes().as_slice(),
|
||||
B_squared.to_le_bytes().as_slice(),
|
||||
t_input.to_le_bytes().as_slice(),
|
||||
msbs_zero_padding_bit_count.to_le_bytes().as_slice(),
|
||||
&*a.iter()
|
||||
.flat_map(|&x| x.to_le_bytes())
|
||||
.collect::<Box<[_]>>(),
|
||||
&*b.iter()
|
||||
.flat_map(|&x| x.to_le_bytes())
|
||||
.collect::<Box<[_]>>(),
|
||||
&*c1.iter()
|
||||
.flat_map(|&x| x.to_le_bytes())
|
||||
.collect::<Box<[_]>>(),
|
||||
&*c2.iter()
|
||||
.flat_map(|&x| x.to_le_bytes())
|
||||
.collect::<Box<[_]>>(),
|
||||
]
|
||||
.iter()
|
||||
.copied()
|
||||
.flatten()
|
||||
.copied()
|
||||
.collect::<Box<[_]>>();
|
||||
let C_hat_e_bytes = C_hat_e.to_le_bytes();
|
||||
let C_e_bytes = C_e.to_le_bytes();
|
||||
let C_r_tilde_bytes = C_r_tilde.to_le_bytes();
|
||||
|
||||
// make R_bar a random number generator from the given bytes
|
||||
use sha3::digest::{ExtendableOutput, Update, XofReader};
|
||||
|
||||
let mut hasher = sha3::Shake256::default();
|
||||
for &data in &[
|
||||
ds.hash_R(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
let (R, R_hash) = RHash::new(
|
||||
public,
|
||||
metadata,
|
||||
x_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
] {
|
||||
hasher.update(data);
|
||||
}
|
||||
let mut R_bar = hasher.finalize_xof();
|
||||
let R = (0..128 * (2 * (d + k) + 4))
|
||||
.map(|_| {
|
||||
let mut byte = 0u8;
|
||||
R_bar.read(core::slice::from_mut(&mut byte));
|
||||
|
||||
// take two bits
|
||||
match byte & 0b11 {
|
||||
// probability 1/2
|
||||
0 | 1 => 0,
|
||||
// probability 1/4
|
||||
2 => 1,
|
||||
// probability 1/4
|
||||
3 => -1,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
})
|
||||
.collect::<Box<[i8]>>();
|
||||
|
||||
C_hat_e_bytes.as_ref(),
|
||||
C_e_bytes.as_ref(),
|
||||
C_r_tilde_bytes.as_ref(),
|
||||
);
|
||||
let R = |i: usize, j: usize| R[i + j * 128];
|
||||
let R_bytes = &*(0..128)
|
||||
.flat_map(|i| (0..(2 * (d + k) + 4)).map(move |j| R(i, j) as u8))
|
||||
.collect::<Box<[u8]>>();
|
||||
|
||||
let w_R = (0..128)
|
||||
.map(|i| {
|
||||
@@ -1041,25 +1007,8 @@ fn prove_impl<G: Curve>(
|
||||
.collect::<Box<[_]>>(),
|
||||
);
|
||||
|
||||
let mut phi = vec![G::Zp::ZERO; 128];
|
||||
G::Zp::hash(
|
||||
&mut phi,
|
||||
&[
|
||||
ds.hash_phi(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
R_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let phi_bytes = &*phi
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
let C_R_bytes = C_R.to_le_bytes();
|
||||
let (phi, phi_hash) = R_hash.gen_phi(C_R_bytes.as_ref());
|
||||
|
||||
let m = m_bound;
|
||||
|
||||
@@ -1082,51 +1031,10 @@ fn prove_impl<G: Curve>(
|
||||
.map(G::G2::projective)
|
||||
.sum::<G::G2>();
|
||||
|
||||
let mut xi = vec![G::Zp::ZERO; 128];
|
||||
G::Zp::hash(
|
||||
&mut xi,
|
||||
&[
|
||||
ds.hash_xi(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
R_bytes,
|
||||
phi_bytes,
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let C_hat_bin_bytes = C_hat_bin.to_le_bytes();
|
||||
let (xi, xi_hash) = phi_hash.gen_xi::<G::Zp>(C_hat_bin_bytes.as_ref());
|
||||
|
||||
let xi_bytes = &*xi
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
|
||||
let mut y = vec![G::Zp::ZERO; D + 128 * m];
|
||||
G::Zp::hash(
|
||||
&mut y,
|
||||
&[
|
||||
ds.hash(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
R_bytes,
|
||||
phi_bytes,
|
||||
xi_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let y_bytes = &*y
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
let (y, y_hash) = xi_hash.gen_y();
|
||||
|
||||
if sanity_check_mode == ProofSanityCheckMode::Panic {
|
||||
assert_eq!(y.len(), w_bin.len());
|
||||
@@ -1140,56 +1048,10 @@ fn prove_impl<G: Curve>(
|
||||
let C_y =
|
||||
g.mul_scalar(gamma_y) + G::G1::multi_mul_scalar(&g_list[n - (D + 128 * m)..n], &scalars);
|
||||
|
||||
let mut t = vec![G::Zp::ZERO; n];
|
||||
G::Zp::hash_128bit(
|
||||
&mut t,
|
||||
&[
|
||||
ds.hash_t(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
y_bytes,
|
||||
phi_bytes,
|
||||
xi_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
R_bytes,
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
C_y.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let t_bytes = &*t
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
let C_y_bytes = C_y.to_le_bytes();
|
||||
let (t, t_hash) = y_hash.gen_t(C_y_bytes.as_ref());
|
||||
|
||||
let mut theta = vec![G::Zp::ZERO; d + k];
|
||||
G::Zp::hash(
|
||||
&mut theta,
|
||||
&[
|
||||
ds.hash_lmap(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
y_bytes,
|
||||
t_bytes,
|
||||
phi_bytes,
|
||||
xi_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
R_bytes,
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
C_y.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let theta_bytes = &*theta
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
let (theta, theta_hash) = t_hash.gen_theta();
|
||||
|
||||
let mut a_theta = vec![G::Zp::ZERO; D];
|
||||
compute_a_theta::<G>(&mut a_theta, &theta, a, k, b, effective_cleartext_t, delta);
|
||||
@@ -1201,61 +1063,10 @@ fn prove_impl<G: Curve>(
|
||||
.map(|(x, y)| x * y)
|
||||
.sum::<G::Zp>();
|
||||
|
||||
let mut w = vec![G::Zp::ZERO; n];
|
||||
G::Zp::hash_128bit(
|
||||
&mut w,
|
||||
&[
|
||||
ds.hash_w(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
y_bytes,
|
||||
t_bytes,
|
||||
phi_bytes,
|
||||
xi_bytes,
|
||||
theta_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
R_bytes,
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
C_y.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let w_bytes = &*w
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
let (omega, omega_hash) = theta_hash.gen_omega();
|
||||
|
||||
let mut delta = [G::Zp::ZERO; 7];
|
||||
G::Zp::hash(
|
||||
&mut delta,
|
||||
&[
|
||||
ds.hash_agg(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
y_bytes,
|
||||
t_bytes,
|
||||
phi_bytes,
|
||||
xi_bytes,
|
||||
theta_bytes,
|
||||
w_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
R_bytes,
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
C_y.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let (delta, delta_hash) = omega_hash.gen_delta::<G::Zp>();
|
||||
let [delta_r, delta_dec, delta_eq, delta_y, delta_theta, delta_e, delta_l] = delta;
|
||||
let delta_bytes = &*delta
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
|
||||
let mut poly_0_lhs = vec![G::Zp::ZERO; 1 + n];
|
||||
let mut poly_0_rhs = vec![G::Zp::ZERO; 1 + D + 128 * m];
|
||||
@@ -1270,7 +1081,7 @@ fn prove_impl<G: Curve>(
|
||||
let mut poly_5_lhs = vec![G::Zp::ZERO; 1 + n];
|
||||
let mut poly_5_rhs = vec![G::Zp::ZERO; 1 + n];
|
||||
|
||||
let mut xi_scaled = xi.clone();
|
||||
let mut xi_scaled = xi;
|
||||
poly_0_lhs[0] = delta_y * gamma_y;
|
||||
for j in 0..D + 128 * m {
|
||||
let p = &mut poly_0_lhs[n - j];
|
||||
@@ -1326,7 +1137,7 @@ fn prove_impl<G: Curve>(
|
||||
|
||||
for j in 0..n {
|
||||
let p = &mut poly_1_lhs[n - j];
|
||||
let mut acc = delta_e * w[j];
|
||||
let mut acc = delta_e * omega[j];
|
||||
if j < d + k {
|
||||
acc += delta_theta * theta[j];
|
||||
}
|
||||
@@ -1413,7 +1224,7 @@ fn prove_impl<G: Curve>(
|
||||
|
||||
for j in 0..d + k + 4 {
|
||||
let p = &mut poly_4_rhs[1 + j];
|
||||
*p = w[j];
|
||||
*p = omega[j];
|
||||
}
|
||||
|
||||
poly_5_lhs[0] = delta_eq * gamma_y;
|
||||
@@ -1507,7 +1318,7 @@ fn prove_impl<G: Curve>(
|
||||
g.mul_scalar(P_pi[0]) + G::G1::multi_mul_scalar(&g_list[..P_pi.len() - 1], &P_pi[1..])
|
||||
};
|
||||
|
||||
let mut xi_scaled = xi.clone();
|
||||
let mut xi_scaled = xi;
|
||||
let mut scalars = (0..D + 128 * m)
|
||||
.map(|j| {
|
||||
let mut acc = G::Zp::ZERO;
|
||||
@@ -1545,7 +1356,7 @@ fn prove_impl<G: Curve>(
|
||||
acc += delta_theta * theta[j];
|
||||
}
|
||||
|
||||
acc += delta_e * w[j];
|
||||
acc += delta_e * omega[j];
|
||||
|
||||
if j < d + k + 4 {
|
||||
let mut acc2 = G::Zp::ZERO;
|
||||
@@ -1587,7 +1398,7 @@ fn prove_impl<G: Curve>(
|
||||
.collect::<Box<[_]>>(),
|
||||
)
|
||||
},
|
||||
|| G::G2::multi_mul_scalar(&g_hat_list[..d + k + 4], &w[..d + k + 4]),
|
||||
|| G::G2::multi_mul_scalar(&g_hat_list[..d + k + 4], &omega[..d + k + 4]),
|
||||
);
|
||||
|
||||
Some(ComputeLoadProofFields { C_hat_h3, C_hat_w })
|
||||
@@ -1595,49 +1406,21 @@ fn prove_impl<G: Curve>(
|
||||
ComputeLoad::Verify => None,
|
||||
};
|
||||
|
||||
let byte_generators =
|
||||
if let Some(ComputeLoadProofFields { C_hat_h3, C_hat_w }) = compute_load_proof_fields {
|
||||
Some((G::G2::to_le_bytes(C_hat_h3), G::G2::to_le_bytes(C_hat_w)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let (C_hat_h3_bytes, C_hat_w_bytes): (&[u8], &[u8]) =
|
||||
if let Some((C_hat_h3_bytes_owner, C_hat_w_bytes_owner)) = byte_generators.as_ref() {
|
||||
(C_hat_h3_bytes_owner.as_ref(), C_hat_w_bytes_owner.as_ref())
|
||||
} else {
|
||||
(&[], &[])
|
||||
};
|
||||
|
||||
let C_hat_t = G::G2::multi_mul_scalar(g_hat_list, &t);
|
||||
|
||||
let mut z = G::Zp::ZERO;
|
||||
G::Zp::hash(
|
||||
core::slice::from_mut(&mut z),
|
||||
&[
|
||||
ds.hash_z(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
y_bytes,
|
||||
t_bytes,
|
||||
phi_bytes,
|
||||
x_bytes,
|
||||
theta_bytes,
|
||||
delta_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
R_bytes,
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
C_y.to_le_bytes().as_ref(),
|
||||
C_h1.to_le_bytes().as_ref(),
|
||||
C_h2.to_le_bytes().as_ref(),
|
||||
C_hat_t.to_le_bytes().as_ref(),
|
||||
C_hat_h3_bytes,
|
||||
C_hat_w_bytes,
|
||||
],
|
||||
let (C_hat_h3_bytes, C_hat_w_bytes) =
|
||||
ComputeLoadProofFields::to_le_bytes(&compute_load_proof_fields);
|
||||
|
||||
let C_h1_bytes = C_h1.to_le_bytes();
|
||||
let C_h2_bytes = C_h2.to_le_bytes();
|
||||
let C_hat_t_bytes = C_hat_t.to_le_bytes();
|
||||
|
||||
let (z, z_hash) = delta_hash.gen_z(
|
||||
C_h1_bytes.as_ref(),
|
||||
C_h2_bytes.as_ref(),
|
||||
C_hat_t_bytes.as_ref(),
|
||||
&C_hat_h3_bytes,
|
||||
&C_hat_w_bytes,
|
||||
);
|
||||
|
||||
let mut P_h1 = vec![G::Zp::ZERO; 1 + n];
|
||||
@@ -1652,7 +1435,7 @@ fn prove_impl<G: Curve>(
|
||||
ComputeLoad::Verify => vec![],
|
||||
};
|
||||
|
||||
let mut xi_scaled = xi.clone();
|
||||
let mut xi_scaled = xi;
|
||||
for j in 0..D + 128 * m {
|
||||
let p = &mut P_h1[n - j];
|
||||
if j < D {
|
||||
@@ -1684,7 +1467,7 @@ fn prove_impl<G: Curve>(
|
||||
*p += delta_theta * theta[j];
|
||||
}
|
||||
|
||||
*p += delta_e * w[j];
|
||||
*p += delta_e * omega[j];
|
||||
|
||||
if j < d + k + 4 {
|
||||
let mut acc = G::Zp::ZERO;
|
||||
@@ -1720,7 +1503,7 @@ fn prove_impl<G: Curve>(
|
||||
}
|
||||
|
||||
if !P_w.is_empty() {
|
||||
P_w[1..].copy_from_slice(&w[..d + k + 4]);
|
||||
P_w[1..].copy_from_slice(&omega[..d + k + 4]);
|
||||
}
|
||||
|
||||
let mut p_h1 = G::Zp::ZERO;
|
||||
@@ -1745,38 +1528,7 @@ fn prove_impl<G: Curve>(
|
||||
pow = pow * z;
|
||||
}
|
||||
|
||||
let mut chi = G::Zp::ZERO;
|
||||
G::Zp::hash(
|
||||
core::slice::from_mut(&mut chi),
|
||||
&[
|
||||
ds.hash_chi(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
y_bytes,
|
||||
t_bytes,
|
||||
phi_bytes,
|
||||
xi_bytes,
|
||||
theta_bytes,
|
||||
delta_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
R_bytes,
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
C_y.to_le_bytes().as_ref(),
|
||||
C_h1.to_le_bytes().as_ref(),
|
||||
C_h2.to_le_bytes().as_ref(),
|
||||
C_hat_t.to_le_bytes().as_ref(),
|
||||
C_hat_h3_bytes,
|
||||
C_hat_w_bytes,
|
||||
z.to_le_bytes().as_ref(),
|
||||
p_h1.to_le_bytes().as_ref(),
|
||||
p_h2.to_le_bytes().as_ref(),
|
||||
p_t.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let chi = z_hash.gen_chi(p_h1, p_h2, p_t);
|
||||
|
||||
let mut Q_kzg = vec![G::Zp::ZERO; 1 + n];
|
||||
let chi2 = chi * chi;
|
||||
@@ -1967,8 +1719,8 @@ pub fn verify_impl<G: Curve>(
|
||||
t: t_input,
|
||||
msbs_zero_padding_bit_count,
|
||||
bound_type,
|
||||
sid,
|
||||
domain_separators: ref ds,
|
||||
sid: _,
|
||||
domain_separators: _,
|
||||
} = public.0;
|
||||
let g_list = &*g_lists.g_list.0;
|
||||
let g_hat_list = &*g_lists.g_hat_list.0;
|
||||
@@ -2004,227 +1756,31 @@ pub fn verify_impl<G: Curve>(
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let byte_generators = if let Some(&ComputeLoadProofFields { C_hat_h3, C_hat_w }) =
|
||||
compute_load_proof_fields.as_ref()
|
||||
{
|
||||
Some((G::G2::to_le_bytes(C_hat_h3), G::G2::to_le_bytes(C_hat_w)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let C_hat_e_bytes = C_hat_e.to_le_bytes();
|
||||
let C_e_bytes = C_e.to_le_bytes();
|
||||
let C_r_tilde_bytes = C_r_tilde.to_le_bytes();
|
||||
|
||||
let (C_hat_h3_bytes, C_hat_w_bytes): (&[u8], &[u8]) =
|
||||
if let Some((C_hat_h3_bytes_owner, C_hat_w_bytes_owner)) = byte_generators.as_ref() {
|
||||
(C_hat_h3_bytes_owner.as_ref(), C_hat_w_bytes_owner.as_ref())
|
||||
} else {
|
||||
(&[], &[])
|
||||
};
|
||||
|
||||
let x_bytes = &*[
|
||||
q.to_le_bytes().as_slice(),
|
||||
(d as u64).to_le_bytes().as_slice(),
|
||||
B_squared.to_le_bytes().as_slice(),
|
||||
t_input.to_le_bytes().as_slice(),
|
||||
msbs_zero_padding_bit_count.to_le_bytes().as_slice(),
|
||||
&*a.iter()
|
||||
.flat_map(|&x| x.to_le_bytes())
|
||||
.collect::<Box<[_]>>(),
|
||||
&*b.iter()
|
||||
.flat_map(|&x| x.to_le_bytes())
|
||||
.collect::<Box<[_]>>(),
|
||||
&*c1.iter()
|
||||
.flat_map(|&x| x.to_le_bytes())
|
||||
.collect::<Box<[_]>>(),
|
||||
&*c2.iter()
|
||||
.flat_map(|&x| x.to_le_bytes())
|
||||
.collect::<Box<[_]>>(),
|
||||
]
|
||||
.iter()
|
||||
.copied()
|
||||
.flatten()
|
||||
.copied()
|
||||
.collect::<Box<[_]>>();
|
||||
|
||||
// make R_bar a random number generator from the given bytes
|
||||
use sha3::digest::{ExtendableOutput, Update, XofReader};
|
||||
|
||||
let mut hasher = sha3::Shake256::default();
|
||||
for &data in &[
|
||||
ds.hash_R(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
let (R, R_hash) = RHash::new(
|
||||
public,
|
||||
metadata,
|
||||
x_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
] {
|
||||
hasher.update(data);
|
||||
}
|
||||
let mut R_bar = hasher.finalize_xof();
|
||||
let R = (0..128 * (2 * (d + k) + 4))
|
||||
.map(|_| {
|
||||
let mut byte = 0u8;
|
||||
R_bar.read(core::slice::from_mut(&mut byte));
|
||||
|
||||
// take two bits
|
||||
match byte & 0b11 {
|
||||
// probability 1/2
|
||||
0 | 1 => 0,
|
||||
// probability 1/4
|
||||
2 => 1,
|
||||
// probability 1/4
|
||||
3 => -1,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
})
|
||||
.collect::<Box<[i8]>>();
|
||||
|
||||
C_hat_e_bytes.as_ref(),
|
||||
C_e_bytes.as_ref(),
|
||||
C_r_tilde_bytes.as_ref(),
|
||||
);
|
||||
let R = |i: usize, j: usize| R[i + j * 128];
|
||||
let R_bytes = &*(0..128)
|
||||
.flat_map(|i| (0..(2 * (d + k) + 4)).map(move |j| R(i, j) as u8))
|
||||
.collect::<Box<[u8]>>();
|
||||
|
||||
let mut phi = vec![G::Zp::ZERO; 128];
|
||||
G::Zp::hash(
|
||||
&mut phi,
|
||||
&[
|
||||
ds.hash_phi(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
R_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let phi_bytes = &*phi
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
let C_R_bytes = C_R.to_le_bytes();
|
||||
let (phi, phi_hash) = R_hash.gen_phi(C_R_bytes.as_ref());
|
||||
|
||||
let mut xi = vec![G::Zp::ZERO; 128];
|
||||
G::Zp::hash(
|
||||
&mut xi,
|
||||
&[
|
||||
ds.hash_xi(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
R_bytes,
|
||||
phi_bytes,
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let xi_bytes = &*xi
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
let C_hat_bin_bytes = C_hat_bin.to_le_bytes();
|
||||
let (xi, xi_hash) = phi_hash.gen_xi::<G::Zp>(C_hat_bin_bytes.as_ref());
|
||||
|
||||
let mut y = vec![G::Zp::ZERO; D + 128 * m];
|
||||
G::Zp::hash(
|
||||
&mut y,
|
||||
&[
|
||||
ds.hash(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
R_bytes,
|
||||
phi_bytes,
|
||||
xi_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let y_bytes = &*y
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
let (y, y_hash) = xi_hash.gen_y();
|
||||
|
||||
let mut t = vec![G::Zp::ZERO; n];
|
||||
G::Zp::hash_128bit(
|
||||
&mut t,
|
||||
&[
|
||||
ds.hash_t(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
y_bytes,
|
||||
phi_bytes,
|
||||
xi_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
R_bytes,
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
C_y.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let t_bytes = &*t
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
let C_y_bytes = C_y.to_le_bytes();
|
||||
let (t, t_hash) = y_hash.gen_t(C_y_bytes.as_ref());
|
||||
|
||||
let mut theta = vec![G::Zp::ZERO; d + k];
|
||||
G::Zp::hash(
|
||||
&mut theta,
|
||||
&[
|
||||
ds.hash_lmap(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
y_bytes,
|
||||
t_bytes,
|
||||
phi_bytes,
|
||||
xi_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
R_bytes,
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
C_y.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let theta_bytes = &*theta
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
|
||||
let mut w = vec![G::Zp::ZERO; n];
|
||||
G::Zp::hash_128bit(
|
||||
&mut w,
|
||||
&[
|
||||
ds.hash_w(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
y_bytes,
|
||||
t_bytes,
|
||||
phi_bytes,
|
||||
xi_bytes,
|
||||
theta_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
R_bytes,
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
C_y.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let w_bytes = &*w
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
let (theta, theta_hash) = t_hash.gen_theta();
|
||||
|
||||
let mut a_theta = vec![G::Zp::ZERO; D];
|
||||
compute_a_theta::<G>(&mut a_theta, &theta, a, k, b, effective_cleartext_t, delta);
|
||||
@@ -2236,34 +1792,10 @@ pub fn verify_impl<G: Curve>(
|
||||
.map(|(x, y)| x * y)
|
||||
.sum::<G::Zp>();
|
||||
|
||||
let mut delta = [G::Zp::ZERO; 7];
|
||||
G::Zp::hash(
|
||||
&mut delta,
|
||||
&[
|
||||
ds.hash_agg(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
y_bytes,
|
||||
t_bytes,
|
||||
phi_bytes,
|
||||
xi_bytes,
|
||||
theta_bytes,
|
||||
w_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
R_bytes,
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
C_y.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let (omega, omega_hash) = theta_hash.gen_omega();
|
||||
|
||||
let (delta, delta_hash) = omega_hash.gen_delta();
|
||||
let [delta_r, delta_dec, delta_eq, delta_y, delta_theta, delta_e, delta_l] = delta;
|
||||
let delta_bytes = &*delta
|
||||
.iter()
|
||||
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
|
||||
.collect::<Box<[_]>>();
|
||||
|
||||
let g = G::G1::GENERATOR;
|
||||
let g_hat = G::G2::GENERATOR;
|
||||
@@ -2319,7 +1851,7 @@ pub fn verify_impl<G: Curve>(
|
||||
C_hat_h3: _,
|
||||
C_hat_w,
|
||||
}) => C_hat_w,
|
||||
None => G::G2::multi_mul_scalar(&g_hat_list[..d + k + 4], &w[..d + k + 4]),
|
||||
None => G::G2::multi_mul_scalar(&g_hat_list[..d + k + 4], &omega[..d + k + 4]),
|
||||
},
|
||||
);
|
||||
let lhs5 = pairing(C_y.mul_scalar(delta_eq), C_hat_t);
|
||||
@@ -2336,41 +1868,27 @@ pub fn verify_impl<G: Curve>(
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let mut z = G::Zp::ZERO;
|
||||
G::Zp::hash(
|
||||
core::slice::from_mut(&mut z),
|
||||
&[
|
||||
ds.hash_z(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
y_bytes,
|
||||
t_bytes,
|
||||
phi_bytes,
|
||||
x_bytes,
|
||||
theta_bytes,
|
||||
delta_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
R_bytes,
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
C_y.to_le_bytes().as_ref(),
|
||||
C_h1.to_le_bytes().as_ref(),
|
||||
C_h2.to_le_bytes().as_ref(),
|
||||
C_hat_t.to_le_bytes().as_ref(),
|
||||
C_hat_h3_bytes,
|
||||
C_hat_w_bytes,
|
||||
],
|
||||
);
|
||||
|
||||
let load = if compute_load_proof_fields.is_some() {
|
||||
ComputeLoad::Proof
|
||||
} else {
|
||||
ComputeLoad::Verify
|
||||
};
|
||||
|
||||
let (C_hat_h3_bytes, C_hat_w_bytes) =
|
||||
ComputeLoadProofFields::to_le_bytes(compute_load_proof_fields);
|
||||
|
||||
let C_h1_bytes = C_h1.to_le_bytes();
|
||||
let C_h2_bytes = C_h2.to_le_bytes();
|
||||
let C_hat_t_bytes = C_hat_t.to_le_bytes();
|
||||
|
||||
let (z, z_hash) = delta_hash.gen_z(
|
||||
C_h1_bytes.as_ref(),
|
||||
C_h2_bytes.as_ref(),
|
||||
C_hat_t_bytes.as_ref(),
|
||||
&C_hat_h3_bytes,
|
||||
&C_hat_w_bytes,
|
||||
);
|
||||
|
||||
let mut P_h1 = vec![G::Zp::ZERO; 1 + n];
|
||||
let mut P_h2 = vec![G::Zp::ZERO; 1 + n];
|
||||
let mut P_t = vec![G::Zp::ZERO; 1 + n];
|
||||
@@ -2383,7 +1901,7 @@ pub fn verify_impl<G: Curve>(
|
||||
ComputeLoad::Verify => vec![],
|
||||
};
|
||||
|
||||
let mut xi_scaled = xi.clone();
|
||||
let mut xi_scaled = xi;
|
||||
for j in 0..D + 128 * m {
|
||||
let p = &mut P_h1[n - j];
|
||||
if j < D {
|
||||
@@ -2415,7 +1933,7 @@ pub fn verify_impl<G: Curve>(
|
||||
*p += delta_theta * theta[j];
|
||||
}
|
||||
|
||||
*p += delta_e * w[j];
|
||||
*p += delta_e * omega[j];
|
||||
|
||||
if j < d + k + 4 {
|
||||
let mut acc = G::Zp::ZERO;
|
||||
@@ -2451,7 +1969,7 @@ pub fn verify_impl<G: Curve>(
|
||||
}
|
||||
|
||||
if !P_w.is_empty() {
|
||||
P_w[1..].copy_from_slice(&w[..d + k + 4]);
|
||||
P_w[1..].copy_from_slice(&omega[..d + k + 4]);
|
||||
}
|
||||
|
||||
let mut p_h1 = G::Zp::ZERO;
|
||||
@@ -2476,38 +1994,8 @@ pub fn verify_impl<G: Curve>(
|
||||
pow = pow * z;
|
||||
}
|
||||
|
||||
let mut chi = G::Zp::ZERO;
|
||||
G::Zp::hash(
|
||||
core::slice::from_mut(&mut chi),
|
||||
&[
|
||||
ds.hash_chi(),
|
||||
sid.to_le_bytes().as_slice(),
|
||||
metadata,
|
||||
x_bytes,
|
||||
y_bytes,
|
||||
t_bytes,
|
||||
phi_bytes,
|
||||
xi_bytes,
|
||||
theta_bytes,
|
||||
delta_bytes,
|
||||
C_hat_e.to_le_bytes().as_ref(),
|
||||
C_e.to_le_bytes().as_ref(),
|
||||
R_bytes,
|
||||
C_R.to_le_bytes().as_ref(),
|
||||
C_hat_bin.to_le_bytes().as_ref(),
|
||||
C_r_tilde.to_le_bytes().as_ref(),
|
||||
C_y.to_le_bytes().as_ref(),
|
||||
C_h1.to_le_bytes().as_ref(),
|
||||
C_h2.to_le_bytes().as_ref(),
|
||||
C_hat_t.to_le_bytes().as_ref(),
|
||||
C_hat_h3_bytes,
|
||||
C_hat_w_bytes,
|
||||
z.to_le_bytes().as_ref(),
|
||||
p_h1.to_le_bytes().as_ref(),
|
||||
p_h2.to_le_bytes().as_ref(),
|
||||
p_t.to_le_bytes().as_ref(),
|
||||
],
|
||||
);
|
||||
let chi = z_hash.gen_chi(p_h1, p_h2, p_t);
|
||||
|
||||
let chi2 = chi * chi;
|
||||
let chi3 = chi2 * chi;
|
||||
let chi4 = chi3 * chi;
|
||||
Reference in New Issue
Block a user