Skip to content

Commit 1659b73

Browse files
committed
use randomized pairing checker in SAVER verifiable decryption
Signed-off-by: lovesh <lovesh.bond@gmail.com>
1 parent 29c9a34 commit 1659b73

File tree

2 files changed

+184
-2
lines changed

2 files changed

+184
-2
lines changed

proof_system/tests/saver.rs

+78-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use ark_std::{
66
UniformRand,
77
};
88
use blake2::Blake2b512;
9+
use dock_crypto_utils::randomized_pairing_check::RandomizedPairingChecker;
910
use proof_system::{
1011
prelude::{
1112
generate_snark_srs_bound_check, EqualWitnesses, MetaStatements, ProofSpec, ProverConfig,
@@ -41,7 +42,6 @@ use saver::{
4142
setup::{setup_for_groth16, ChunkedCommitmentGens, EncryptionGens, PreparedEncryptionGens},
4243
};
4344
use std::time::Instant;
44-
4545
use test_utils::{bbs::*, test_serialization};
4646

4747
pub fn decrypt_and_verify(
@@ -54,12 +54,14 @@ pub fn decrypt_and_verify(
5454
enc_gens: impl Into<PreparedEncryptionGens<Bls12_381>>,
5555
chunk_bit_size: u8,
5656
) {
57+
let start = Instant::now();
5758
let dk = dk.into();
5859
let enc_gens = enc_gens.into();
5960
let ct = proof.get_saver_ciphertext_and_proof(stmt_idx).unwrap().0;
6061
let (decrypted_message, nu) = ct
6162
.decrypt_given_groth16_vk(sk, dk.clone(), snark_vk, chunk_bit_size)
6263
.unwrap();
64+
println!("Time to decrypt {:?}", start.elapsed());
6365
assert_eq!(decrypted_message, decrypted);
6466
ct.verify_decryption_given_groth16_vk(
6567
&decrypted_message,
@@ -72,6 +74,38 @@ pub fn decrypt_and_verify(
7274
.unwrap();
7375
}
7476

77+
pub fn decrypt_and_verify_with_randomized_pairing_checker(
78+
pairing_checker: &mut RandomizedPairingChecker<Bls12_381>,
79+
proof: &Proof<Bls12_381>,
80+
stmt_idx: usize,
81+
snark_vk: &VerifyingKey<Bls12_381>,
82+
decrypted: Fr,
83+
sk: &SecretKey<Fr>,
84+
dk: impl Into<PreparedDecryptionKey<Bls12_381>>,
85+
enc_gens: impl Into<PreparedEncryptionGens<Bls12_381>>,
86+
chunk_bit_size: u8,
87+
) {
88+
let start = Instant::now();
89+
let dk = dk.into();
90+
let enc_gens = enc_gens.into();
91+
let ct = proof.get_saver_ciphertext_and_proof(stmt_idx).unwrap().0;
92+
let (decrypted_message, nu) = ct
93+
.decrypt_given_groth16_vk(sk, dk.clone(), snark_vk, chunk_bit_size)
94+
.unwrap();
95+
println!("Time to decrypt {:?}", start.elapsed());
96+
assert_eq!(decrypted_message, decrypted);
97+
ct.verify_decryption_given_groth16_vk_with_randomized_pairing_checker(
98+
&decrypted_message,
99+
&nu,
100+
chunk_bit_size,
101+
dk,
102+
snark_vk,
103+
enc_gens,
104+
pairing_checker,
105+
)
106+
.unwrap();
107+
}
108+
75109
macro_rules! gen_tests {
76110
($test1_name: ident, $test2_name: ident, $setup_fn_name: ident, $prover_stmt: ident, $verifier_stmt: ident, $wit: ident) => {
77111
#[test]
@@ -262,6 +296,26 @@ macro_rules! gen_tests {
262296
start.elapsed()
263297
);
264298

299+
let start = Instant::now();
300+
let mut checker = RandomizedPairingChecker::<Bls12_381>::new_using_rng(&mut rng, true);
301+
decrypt_and_verify_with_randomized_pairing_checker(
302+
&mut checker,
303+
&proof,
304+
1,
305+
&snark_pk.pk.vk,
306+
msgs[enc_msg_idx],
307+
&sk,
308+
prepared_dk.clone(),
309+
prepared_enc_gens.clone(),
310+
chunk_bit_size,
311+
);
312+
assert!(checker.verify());
313+
println!(
314+
"Time taken to decrypt and verify 1 encrypted message in signature over {} messages using randomized pairing checker {:?}",
315+
msg_count,
316+
start.elapsed()
317+
);
318+
265319
let start = Instant::now();
266320
let mut m = BTreeMap::new();
267321
let (c, p) = proof.get_saver_ciphertext_and_proof(1).unwrap();
@@ -616,6 +670,29 @@ macro_rules! gen_tests {
616670
start.elapsed()
617671
);
618672

673+
let start = Instant::now();
674+
let mut checker = RandomizedPairingChecker::<Bls12_381>::new_using_rng(&mut rng, true);
675+
for (i, j) in enc_msg_indices.iter().enumerate() {
676+
decrypt_and_verify_with_randomized_pairing_checker(
677+
&mut checker,
678+
&proof,
679+
i + 1,
680+
&snark_pk.pk.vk,
681+
msgs[*j],
682+
&sk,
683+
dk.clone(),
684+
enc_gens.clone(),
685+
chunk_bit_size,
686+
);
687+
}
688+
assert!(checker.verify());
689+
println!(
690+
"Time taken to decrypt and verify {} encrypted messages in signature over {} messages using randomized pairing checker {:?}",
691+
enc_msg_indices.len(),
692+
msg_count,
693+
start.elapsed()
694+
);
695+
619696
let start = Instant::now();
620697
let mut m = BTreeMap::new();
621698
for i in 1..=enc_msg_indices.len() {

saver/src/encryption.rs

+106-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ use serde_with::serde_as;
2929
use crate::utils::CHUNK_TYPE;
3030
use dock_crypto_utils::{ff::non_zero_random, serde_utils::*};
3131

32-
use dock_crypto_utils::solve_discrete_log::solve_discrete_log_bsgs_alt;
32+
use dock_crypto_utils::{
33+
randomized_pairing_check::RandomizedPairingChecker,
34+
solve_discrete_log::solve_discrete_log_bsgs_alt,
35+
};
3336
#[cfg(feature = "parallel")]
3437
use rayon::prelude::*;
3538

@@ -127,6 +130,31 @@ macro_rules! impl_enc_funcs {
127130
gens,
128131
)
129132
}
133+
134+
/// Verify that the decrypted message corresponds to original plaintext in the ciphertext
135+
/// but using randomized pairing checker
136+
pub fn verify_decryption_with_randomized_pairing_checker(
137+
&self,
138+
message: &E::ScalarField,
139+
nu: &E::G1Affine,
140+
chunk_bit_size: u8,
141+
dk: impl Into<PreparedDecryptionKey<E>>,
142+
g_i: &[E::G1Affine],
143+
gens: impl Into<PreparedEncryptionGens<E>>,
144+
pairing_checker: &mut RandomizedPairingChecker<E>,
145+
) -> crate::Result<()> {
146+
let decomposed = utils::decompose(message, chunk_bit_size)?;
147+
Encryption::verify_decryption_with_randomized_pairing_checker(
148+
&decomposed,
149+
&self.X_r,
150+
&self.enc_chunks,
151+
nu,
152+
dk,
153+
g_i,
154+
gens,
155+
pairing_checker,
156+
)
157+
}
130158
};
131159
}
132160

@@ -439,6 +467,61 @@ impl<E: Pairing> Encryption<E> {
439467
Ok(())
440468
}
441469

470+
/// Same as `Self::verify_decryption` but used randomized pairing checker
471+
pub fn verify_decryption_with_randomized_pairing_checker(
472+
messages: &[CHUNK_TYPE],
473+
c_0: &E::G1Affine,
474+
c: &[E::G1Affine],
475+
nu: &E::G1Affine,
476+
dk: impl Into<PreparedDecryptionKey<E>>,
477+
g_i: &[E::G1Affine],
478+
gens: impl Into<PreparedEncryptionGens<E>>,
479+
pairing_checker: &mut RandomizedPairingChecker<E>,
480+
) -> crate::Result<()> {
481+
let dk = dk.into();
482+
let gens = gens.into();
483+
if messages.len() != dk.supported_chunks_count()? as usize {
484+
return Err(SaverError::IncompatibleDecryptionKey(
485+
messages.len(),
486+
dk.supported_chunks_count()? as usize,
487+
));
488+
}
489+
if messages.len() > g_i.len() {
490+
return Err(SaverError::VectorShorterThanExpected(
491+
messages.len(),
492+
g_i.len(),
493+
));
494+
}
495+
496+
// NOTE: A likely optimization is combining all terms involving `nu` and then use a random linear
497+
// combination check but this will require multiplication in group G2, i.e. gens.H and dk.V_1
498+
// which is not possible given prepared versions of these. So it needs to be compared with the
499+
// other variation
500+
501+
let minus_nu = nu.into_group().neg().into();
502+
pairing_checker.add_sources(nu, gens.H, c_0, dk.V_0.clone());
503+
504+
let g_i_m_i_c_i = E::G1::normalize_batch(
505+
// g_i * m_i - c_i
506+
&cfg_into_iter!(0..messages.len())
507+
.map(|i| {
508+
let g_i_m_i = g_i[i].mul(E::ScalarField::from(messages[i] as u64));
509+
g_i_m_i.sub(&c[i])
510+
})
511+
.collect::<Vec<_>>(),
512+
);
513+
514+
for i in 0..messages.len() {
515+
pairing_checker.add_sources(
516+
&g_i_m_i_c_i[i],
517+
dk.V_2[i].clone(),
518+
&minus_nu,
519+
dk.V_1[i].clone(),
520+
);
521+
}
522+
Ok(())
523+
}
524+
442525
/// Same as `Self::verify_decryption` but takes Groth16's verification key instead of the generators used for Elgamal encryption
443526
pub fn verify_decryption_given_groth16_vk(
444527
messages: &[CHUNK_TYPE],
@@ -718,6 +801,28 @@ impl<E: Pairing> Ciphertext<E> {
718801
let g_i = saver_groth16::get_gs_for_encryption(snark_vk);
719802
self.verify_decryption(message, nu, chunk_bit_size, dk, g_i, gens)
720803
}
804+
805+
pub fn verify_decryption_given_groth16_vk_with_randomized_pairing_checker(
806+
&self,
807+
message: &E::ScalarField,
808+
nu: &E::G1Affine,
809+
chunk_bit_size: u8,
810+
dk: impl Into<PreparedDecryptionKey<E>>,
811+
snark_vk: &ark_groth16::VerifyingKey<E>,
812+
gens: impl Into<PreparedEncryptionGens<E>>,
813+
pairing_checker: &mut RandomizedPairingChecker<E>,
814+
) -> crate::Result<()> {
815+
let g_i = saver_groth16::get_gs_for_encryption(snark_vk);
816+
self.verify_decryption_with_randomized_pairing_checker(
817+
message,
818+
nu,
819+
chunk_bit_size,
820+
dk,
821+
g_i,
822+
gens,
823+
pairing_checker,
824+
)
825+
}
721826
}
722827

723828
impl<E: Pairing> CiphertextAlt<E> {

0 commit comments

Comments
 (0)