Skip to content

Commit

Permalink
use randomized pairing checker in SAVER verifiable decryption
Browse files Browse the repository at this point in the history
Signed-off-by: lovesh <[email protected]>
  • Loading branch information
lovesh committed Oct 8, 2024
1 parent 29c9a34 commit 1659b73
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 2 deletions.
79 changes: 78 additions & 1 deletion proof_system/tests/saver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use ark_std::{
UniformRand,
};
use blake2::Blake2b512;
use dock_crypto_utils::randomized_pairing_check::RandomizedPairingChecker;
use proof_system::{
prelude::{
generate_snark_srs_bound_check, EqualWitnesses, MetaStatements, ProofSpec, ProverConfig,
Expand Down Expand Up @@ -41,7 +42,6 @@ use saver::{
setup::{setup_for_groth16, ChunkedCommitmentGens, EncryptionGens, PreparedEncryptionGens},
};
use std::time::Instant;

use test_utils::{bbs::*, test_serialization};

pub fn decrypt_and_verify(
Expand All @@ -54,12 +54,14 @@ pub fn decrypt_and_verify(
enc_gens: impl Into<PreparedEncryptionGens<Bls12_381>>,
chunk_bit_size: u8,
) {
let start = Instant::now();
let dk = dk.into();
let enc_gens = enc_gens.into();
let ct = proof.get_saver_ciphertext_and_proof(stmt_idx).unwrap().0;
let (decrypted_message, nu) = ct
.decrypt_given_groth16_vk(sk, dk.clone(), snark_vk, chunk_bit_size)
.unwrap();
println!("Time to decrypt {:?}", start.elapsed());
assert_eq!(decrypted_message, decrypted);
ct.verify_decryption_given_groth16_vk(
&decrypted_message,
Expand All @@ -72,6 +74,38 @@ pub fn decrypt_and_verify(
.unwrap();
}

pub fn decrypt_and_verify_with_randomized_pairing_checker(
pairing_checker: &mut RandomizedPairingChecker<Bls12_381>,
proof: &Proof<Bls12_381>,
stmt_idx: usize,
snark_vk: &VerifyingKey<Bls12_381>,
decrypted: Fr,
sk: &SecretKey<Fr>,
dk: impl Into<PreparedDecryptionKey<Bls12_381>>,
enc_gens: impl Into<PreparedEncryptionGens<Bls12_381>>,
chunk_bit_size: u8,
) {
let start = Instant::now();
let dk = dk.into();
let enc_gens = enc_gens.into();
let ct = proof.get_saver_ciphertext_and_proof(stmt_idx).unwrap().0;
let (decrypted_message, nu) = ct
.decrypt_given_groth16_vk(sk, dk.clone(), snark_vk, chunk_bit_size)
.unwrap();
println!("Time to decrypt {:?}", start.elapsed());
assert_eq!(decrypted_message, decrypted);
ct.verify_decryption_given_groth16_vk_with_randomized_pairing_checker(
&decrypted_message,
&nu,
chunk_bit_size,
dk,
snark_vk,
enc_gens,
pairing_checker,
)
.unwrap();
}

macro_rules! gen_tests {
($test1_name: ident, $test2_name: ident, $setup_fn_name: ident, $prover_stmt: ident, $verifier_stmt: ident, $wit: ident) => {
#[test]
Expand Down Expand Up @@ -262,6 +296,26 @@ macro_rules! gen_tests {
start.elapsed()
);

let start = Instant::now();
let mut checker = RandomizedPairingChecker::<Bls12_381>::new_using_rng(&mut rng, true);
decrypt_and_verify_with_randomized_pairing_checker(
&mut checker,
&proof,
1,
&snark_pk.pk.vk,
msgs[enc_msg_idx],
&sk,
prepared_dk.clone(),
prepared_enc_gens.clone(),
chunk_bit_size,
);
assert!(checker.verify());
println!(
"Time taken to decrypt and verify 1 encrypted message in signature over {} messages using randomized pairing checker {:?}",
msg_count,
start.elapsed()
);

let start = Instant::now();
let mut m = BTreeMap::new();
let (c, p) = proof.get_saver_ciphertext_and_proof(1).unwrap();
Expand Down Expand Up @@ -616,6 +670,29 @@ macro_rules! gen_tests {
start.elapsed()
);

let start = Instant::now();
let mut checker = RandomizedPairingChecker::<Bls12_381>::new_using_rng(&mut rng, true);
for (i, j) in enc_msg_indices.iter().enumerate() {
decrypt_and_verify_with_randomized_pairing_checker(
&mut checker,
&proof,
i + 1,
&snark_pk.pk.vk,
msgs[*j],
&sk,
dk.clone(),
enc_gens.clone(),
chunk_bit_size,
);
}
assert!(checker.verify());
println!(
"Time taken to decrypt and verify {} encrypted messages in signature over {} messages using randomized pairing checker {:?}",
enc_msg_indices.len(),
msg_count,
start.elapsed()
);

let start = Instant::now();
let mut m = BTreeMap::new();
for i in 1..=enc_msg_indices.len() {
Expand Down
107 changes: 106 additions & 1 deletion saver/src/encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ use serde_with::serde_as;
use crate::utils::CHUNK_TYPE;
use dock_crypto_utils::{ff::non_zero_random, serde_utils::*};

use dock_crypto_utils::solve_discrete_log::solve_discrete_log_bsgs_alt;
use dock_crypto_utils::{
randomized_pairing_check::RandomizedPairingChecker,
solve_discrete_log::solve_discrete_log_bsgs_alt,
};
#[cfg(feature = "parallel")]
use rayon::prelude::*;

Expand Down Expand Up @@ -127,6 +130,31 @@ macro_rules! impl_enc_funcs {
gens,
)
}

/// Verify that the decrypted message corresponds to original plaintext in the ciphertext
/// but using randomized pairing checker
pub fn verify_decryption_with_randomized_pairing_checker(
&self,
message: &E::ScalarField,
nu: &E::G1Affine,
chunk_bit_size: u8,
dk: impl Into<PreparedDecryptionKey<E>>,
g_i: &[E::G1Affine],
gens: impl Into<PreparedEncryptionGens<E>>,
pairing_checker: &mut RandomizedPairingChecker<E>,
) -> crate::Result<()> {
let decomposed = utils::decompose(message, chunk_bit_size)?;
Encryption::verify_decryption_with_randomized_pairing_checker(
&decomposed,
&self.X_r,
&self.enc_chunks,
nu,
dk,
g_i,
gens,
pairing_checker,
)
}
};
}

Expand Down Expand Up @@ -439,6 +467,61 @@ impl<E: Pairing> Encryption<E> {
Ok(())
}

/// Same as `Self::verify_decryption` but used randomized pairing checker
pub fn verify_decryption_with_randomized_pairing_checker(
messages: &[CHUNK_TYPE],
c_0: &E::G1Affine,
c: &[E::G1Affine],
nu: &E::G1Affine,
dk: impl Into<PreparedDecryptionKey<E>>,
g_i: &[E::G1Affine],
gens: impl Into<PreparedEncryptionGens<E>>,
pairing_checker: &mut RandomizedPairingChecker<E>,
) -> crate::Result<()> {
let dk = dk.into();
let gens = gens.into();
if messages.len() != dk.supported_chunks_count()? as usize {
return Err(SaverError::IncompatibleDecryptionKey(
messages.len(),
dk.supported_chunks_count()? as usize,
));
}
if messages.len() > g_i.len() {
return Err(SaverError::VectorShorterThanExpected(
messages.len(),
g_i.len(),
));
}

// NOTE: A likely optimization is combining all terms involving `nu` and then use a random linear
// combination check but this will require multiplication in group G2, i.e. gens.H and dk.V_1
// which is not possible given prepared versions of these. So it needs to be compared with the
// other variation

let minus_nu = nu.into_group().neg().into();
pairing_checker.add_sources(nu, gens.H, c_0, dk.V_0.clone());

let g_i_m_i_c_i = E::G1::normalize_batch(
// g_i * m_i - c_i
&cfg_into_iter!(0..messages.len())
.map(|i| {
let g_i_m_i = g_i[i].mul(E::ScalarField::from(messages[i] as u64));
g_i_m_i.sub(&c[i])
})
.collect::<Vec<_>>(),
);

for i in 0..messages.len() {
pairing_checker.add_sources(
&g_i_m_i_c_i[i],
dk.V_2[i].clone(),
&minus_nu,
dk.V_1[i].clone(),
);
}
Ok(())
}

/// Same as `Self::verify_decryption` but takes Groth16's verification key instead of the generators used for Elgamal encryption
pub fn verify_decryption_given_groth16_vk(
messages: &[CHUNK_TYPE],
Expand Down Expand Up @@ -718,6 +801,28 @@ impl<E: Pairing> Ciphertext<E> {
let g_i = saver_groth16::get_gs_for_encryption(snark_vk);
self.verify_decryption(message, nu, chunk_bit_size, dk, g_i, gens)
}

pub fn verify_decryption_given_groth16_vk_with_randomized_pairing_checker(
&self,
message: &E::ScalarField,
nu: &E::G1Affine,
chunk_bit_size: u8,
dk: impl Into<PreparedDecryptionKey<E>>,
snark_vk: &ark_groth16::VerifyingKey<E>,
gens: impl Into<PreparedEncryptionGens<E>>,
pairing_checker: &mut RandomizedPairingChecker<E>,
) -> crate::Result<()> {
let g_i = saver_groth16::get_gs_for_encryption(snark_vk);
self.verify_decryption_with_randomized_pairing_checker(
message,
nu,
chunk_bit_size,
dk,
g_i,
gens,
pairing_checker,
)
}
}

impl<E: Pairing> CiphertextAlt<E> {
Expand Down

0 comments on commit 1659b73

Please sign in to comment.