Skip to content

Commit

Permalink
Merge pull request anoma#46 from nucypher/verify-simple-tdec-shares
Browse files Browse the repository at this point in the history
piotr-roslaniec authored Feb 6, 2023
2 parents 9050db0 + 48a2513 commit 530de97
Showing 9 changed files with 381 additions and 72 deletions.
46 changes: 35 additions & 11 deletions ferveo/src/lib.rs
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@ mod test_dkg_full {
use crate::dkg::pv::test_common::*;
use ark_bls12_381::{Bls12_381 as EllipticCurve, Bls12_381, G2Projective};
use ark_ec::bls12::G2Affine;
use ark_ec::group::Group;
use ark_ff::{Fp12, UniformRand};
use ferveo_common::{ExternalValidator, Keypair};
use group_threshold_cryptography as tpke;
@@ -54,16 +55,22 @@ mod test_dkg_full {
let msg: &[u8] = "abc".as_bytes();
let aad: &[u8] = "my-aad".as_bytes();
let public_key = dkg.final_key();
let g_inv = dkg.pvss_params.g_inv();

let ciphertext = tpke::encrypt::<_, E>(msg, aad, &public_key, rng);

let aggregate = aggregate_for_decryption(&dkg);
let share_aggregate = aggregate_for_decryption(&dkg);
// Aggregate contains only one set of shares
assert_eq!(aggregate, dkg.vss.get(&0).unwrap().shares);
assert_eq!(share_aggregate, dkg.vss.get(&0).unwrap().shares);

let validator_keypairs = gen_n_keypairs(1);
let decryption_shares =
make_decryption_shares(&ciphertext, validator_keypairs, aggregate);
let decryption_shares = make_decryption_shares(
&ciphertext,
&validator_keypairs,
&share_aggregate,
aad,
&g_inv,
);

let shares_x = &dkg
.domain
@@ -96,11 +103,9 @@ mod test_dkg_full {
let aad: &[u8] = "my-aad".as_bytes();
let public_key = dkg.final_key();
let ciphertext = tpke::encrypt::<_, E>(msg, aad, &public_key, rng);
let g_inv = dkg.pvss_params.g_inv();

let aggregate = aggregate_for_decryption(&dkg);

// TODO: Before creating decryption shares, check ciphertext validity
// See: https://nikkolasg.github.io/ferveo/tpke.html#to-validate-ciphertext-for-ind-cca2-security
let share_aggregate = aggregate_for_decryption(&dkg);

let validator_keypairs = gen_n_keypairs(4);
// Make sure validators are in the same order dkg is by comparing their public keys
@@ -110,13 +115,18 @@ mod test_dkg_full {
.for_each(|(v, k)| {
assert_eq!(v.validator.public_key, k.public());
});
let decryption_shares =
make_decryption_shares(&ciphertext, validator_keypairs, aggregate);
let decryption_shares = make_decryption_shares(
&ciphertext,
&validator_keypairs,
&share_aggregate,
aad,
&g_inv,
);

let shares_x = &dkg
.domain
.elements()
.take(decryption_shares.len())
.take(decryption_shares.len()) // TODO: Assert length instead?
.collect::<Vec<_>>();
let lagrange_coeffs = tpke::prepare_combine_simple::<E>(shares_x);

@@ -125,6 +135,8 @@ mod test_dkg_full {
&lagrange_coeffs,
);

// Combination works, let's decrypt

let plaintext = tpke::checked_decrypt_with_shared_secret(
&ciphertext,
aad,
@@ -133,5 +145,17 @@ mod test_dkg_full {
)
.unwrap();
assert_eq!(plaintext, msg);

// Testing green-path decryption share verification
izip!(decryption_shares, share_aggregate, validator_keypairs).for_each(
|(decryption_share, y_i, validator_keypair)| {
assert!(decryption_share.verify(
&y_i,
&validator_keypair.public().encryption_key,
&dkg.pvss_params.h,
&ciphertext
));
},
);
}
}
39 changes: 25 additions & 14 deletions ferveo/src/vss/pvss.rs
Original file line number Diff line number Diff line change
@@ -8,11 +8,13 @@ use ark_ec::PairingEngine;
use ark_ff::UniformRand;
use ark_serialize::*;
use ferveo_common::{Keypair, PublicKey};
use group_threshold_cryptography::{Ciphertext, DecryptionShareSimple};
use group_threshold_cryptography::{
Ciphertext, DecryptionShareSimple, PrivateKeyShare,
};
use itertools::{zip_eq, Itertools};
use subproductdomain::fast_multiexp;

/// These are the blinded evaluations of weight shares of a single random polynomial
/// These are the blinded evaluations of shares of a single random polynomial
pub type ShareEncryptions<E> = <E as PairingEngine>::G2Affine;

/// Marker struct for unaggregated PVSS transcripts
@@ -261,26 +263,35 @@ pub fn aggregate_for_decryption<E: PairingEngine>(

pub fn make_decryption_shares<E: PairingEngine>(
ciphertext: &Ciphertext<E>,
validator_keypairs: Vec<Keypair<E>>,
aggregate: Vec<E::G2Affine>,
validator_keypairs: &[Keypair<E>],
aggregate: &[E::G2Affine],
aad: &[u8],
g_inv: &E::G1Prepared,
) -> Vec<DecryptionShareSimple<E>> {
// TODO: Calculate separately for each validator
aggregate
.iter()
.zip_eq(validator_keypairs.iter())
.map(|(encrypted_share, keypair)| {
.enumerate()
.map(|(decrypter_index, (encrypted_share, keypair))| {
// Decrypt private key shares https://nikkolasg.github.io/ferveo/pvss.html#validator-decryption-of-private-key-shares
let z_i = encrypted_share
.mul(keypair.decryption_key.inverse().unwrap().into_repr());
let u = ciphertext.commitment;
E::pairing(u, z_i)
})
.enumerate()
.map(
|(decrypter_index, decryption_share)| DecryptionShareSimple {
// TODO: Consider using "container" structs from `tpke` for other primitives
let private_key_share = PrivateKeyShare {
private_key_share: z_i.into_affine(),
};

DecryptionShareSimple::create(
decrypter_index,
decryption_share,
},
)
&keypair.decryption_key,
&private_key_share,
ciphertext,
aad,
g_inv,
)
.unwrap() // Unwrapping here only because this is a test method!
})
.collect::<Vec<_>>()
}

88 changes: 72 additions & 16 deletions tpke/benches/tpke.rs
Original file line number Diff line number Diff line change
@@ -112,15 +112,7 @@ impl SetupSimple {
// Creating decryption shares
let decryption_shares: Vec<_> = contexts
.iter()
.map(|context| {
context
.create_share(
&ciphertext,
aad,
&contexts[0].setup_params.g_inv,
)
.unwrap()
})
.map(|context| context.create_share(&ciphertext, aad).unwrap())
.collect();

let pub_contexts = contexts[0].clone().public_decryption_contexts;
@@ -192,7 +184,6 @@ pub fn bench_create_decryption_share(c: &mut Criterion) {
ctx.create_share(
&setup.shared.ciphertext,
&setup.shared.aad,
&setup.contexts[0].setup_params.g_inv,
)
})
.collect::<Vec<_>>()
@@ -376,15 +367,15 @@ pub fn bench_share_encrypt_decrypt(c: &mut Criterion) {
}
}

pub fn bench_validity_checks(c: &mut Criterion) {
let mut group = c.benchmark_group("VALIDITY CHECKS");
pub fn bench_ciphertext_validity_checks(c: &mut Criterion) {
let mut group = c.benchmark_group("CIPHERTEXT VERIFICATION");
group.sample_size(10);

let rng = &mut StdRng::seed_from_u64(0);
let shares_num = NUM_SHARES_CASES[0];

for msg_size in MSG_SIZE_CASES {
let ciphertext_validity = {
let ciphertext_verification = {
let mut rng = rng.clone();
let setup = SetupFast::new(shares_num, msg_size, &mut rng);
move || {
@@ -397,8 +388,72 @@ pub fn bench_validity_checks(c: &mut Criterion) {
}
};
group.bench_function(
BenchmarkId::new("check_ciphertext_validity", msg_size),
|b| b.iter(|| ciphertext_validity()),
BenchmarkId::new("ciphertext_verification", msg_size),
|b| b.iter(|| ciphertext_verification()),
);
}
}

pub fn bench_decryption_share_validity_checks(c: &mut Criterion) {
let mut group = c.benchmark_group("DECRYPTION SHARE VERIFICATION");
group.sample_size(10);

let rng = &mut StdRng::seed_from_u64(0);
let msg_size = MSG_SIZE_CASES[0];

for shares_num in NUM_SHARES_CASES {
let share_fast_verification = {
let mut rng = rng.clone();
let setup = SetupFast::new(shares_num, msg_size, &mut rng);
move || {
black_box(verify_decryption_shares_fast(
&setup.pub_contexts,
&setup.shared.ciphertext,
&setup.decryption_shares,
))
}
};
group.bench_function(
BenchmarkId::new("share_fast_verification", shares_num),
|b| b.iter(|| share_fast_verification()),
);

let mut share_fast_batch_verification = {
let mut rng = rng.clone();
let setup = SetupFast::new(shares_num, msg_size, &mut rng);
// We need to repackage a bunch of variables here to avoid borrowing issues:
let ciphertext = setup.shared.ciphertext.clone();
let ciphertexts = vec![ciphertext];
let decryption_shares = setup.decryption_shares.clone();
let decryption_shares = vec![decryption_shares];
move || {
black_box(batch_verify_decryption_shares(
&setup.pub_contexts,
&ciphertexts,
&decryption_shares,
&mut rng,
))
}
};
group.bench_function(
BenchmarkId::new("share_fast_batch_verification", shares_num),
|b| b.iter(|| share_fast_batch_verification()),
);

let share_simple_verification = {
let mut rng = rng.clone();
let setup = SetupSimple::new(shares_num, msg_size, &mut rng);
move || {
black_box(verify_decryption_shares_simple(
&setup.pub_contexts,
&setup.shared.ciphertext,
&setup.decryption_shares,
))
}
};
group.bench_function(
BenchmarkId::new("share_simple_verification", shares_num),
|b| b.iter(|| share_simple_verification()),
);
}
}
@@ -470,7 +525,8 @@ criterion_group!(
bench_share_prepare,
bench_share_combine,
bench_share_encrypt_decrypt,
bench_validity_checks,
bench_ciphertext_validity_checks,
bench_decryption_share_validity_checks,
bench_recover_share_at_point,
bench_refresh_shares,
);
3 changes: 2 additions & 1 deletion tpke/src/ciphertext.rs
Original file line number Diff line number Diff line change
@@ -103,7 +103,8 @@ pub fn encrypt<R: RngCore, E: PairingEngine>(
}

/// Implements the check section 4.4.2 of the Ferveo paper, 'TPKE.CheckCiphertextValidity(U,W,aad)'
/// See https://eprint.iacr.org/2022/898.pdf
/// See: https://eprint.iacr.org/2022/898.pdf
/// See: https://nikkolasg.github.io/ferveo/tpke.html#to-validate-ciphertext-for-ind-cca2-security
pub fn check_ciphertext_validity<E: PairingEngine>(
c: &Ciphertext<E>,
aad: &[u8],
1 change: 0 additions & 1 deletion tpke/src/combine.rs
Original file line number Diff line number Diff line change
@@ -100,7 +100,6 @@ pub fn checked_share_combine_fast<E: PairingEngine>(
Ok(share_combine_fast(decryption_shares, prepared_key_shares))
}

// TODO: Hide this from external users. Currently blocked by usage in benchmarks.
pub fn share_combine_simple<E: PairingEngine>(
decryption_shares: &[DecryptionShareSimple<E>],
lagrange_coeffs: &[E::Fr],
24 changes: 13 additions & 11 deletions tpke/src/context.rs
Original file line number Diff line number Diff line change
@@ -16,6 +16,8 @@ pub struct PublicDecryptionContextSimple<E: PairingEngine> {
pub domain: E::Fr,
pub public_key_share: PublicKeyShare<E>,
pub blinded_key_share: BlindedKeyShare<E>,
pub h: E::G2Affine,
pub validator_public_key: E::G2Projective,
}

#[derive(Clone, Debug)]
@@ -63,6 +65,8 @@ pub struct PrivateDecryptionContextSimple<E: PairingEngine> {
pub setup_params: SetupParams<E>,
pub private_key_share: PrivateKeyShare<E>,
pub public_decryption_contexts: Vec<PublicDecryptionContextSimple<E>>,
// TODO: Remove/replace with `setup_params.b` after refactoring
pub validator_private_key: E::Fr,
}

impl<E: PairingEngine> PrivateDecryptionContextSimple<E> {
@@ -71,18 +75,15 @@ impl<E: PairingEngine> PrivateDecryptionContextSimple<E> {
&self,
ciphertext: &Ciphertext<E>,
aad: &[u8],
g_inv: &E::G1Prepared,
) -> Result<DecryptionShareSimple<E>> {
check_ciphertext_validity::<E>(ciphertext, aad, g_inv)?;

let u = ciphertext.commitment;
let z_i = self.private_key_share.private_key_share;
// C_i = e(U, Z_i)
let c_i = E::pairing(u, z_i);
Ok(DecryptionShareSimple {
decrypter_index: self.index,
decryption_share: c_i,
})
DecryptionShareSimple::create(
self.index,
&self.validator_private_key,
&self.private_key_share,
ciphertext,
aad,
&self.setup_params.g_inv,
)
}

pub fn create_share_precomputed(
@@ -96,6 +97,7 @@ impl<E: PairingEngine> PrivateDecryptionContextSimple<E> {
let z_i = self.private_key_share.private_key_share;
// C_{λ_i} = e(U_{λ_i}, Z_i)
let c_i = E::pairing(u_to_lagrange_coeff, z_i);

DecryptionShareSimplePrecomputed {
decrypter_index: self.index,
decryption_share: c_i,
157 changes: 152 additions & 5 deletions tpke/src/decryption.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![allow(non_snake_case)]

use crate::*;
use ark_ec::ProjectiveCurve;

use itertools::zip_eq;

@@ -23,11 +22,11 @@ impl<E: PairingEngine> DecryptionShareFast<E> {
}

pub fn from_bytes(bytes: &[u8]) -> Self {
let INDEX_BYTE_LEN = 8;
let index_byte_len = 8;
let decrypter_index =
bincode::deserialize(&bytes[0..INDEX_BYTE_LEN]).unwrap();
bincode::deserialize(&bytes[0..index_byte_len]).unwrap();
let decryption_share =
CanonicalDeserialize::deserialize(&bytes[INDEX_BYTE_LEN..])
CanonicalDeserialize::deserialize(&bytes[index_byte_len..])
.unwrap();

DecryptionShareFast {
@@ -39,8 +38,131 @@ impl<E: PairingEngine> DecryptionShareFast<E> {

#[derive(Debug, Clone)]
pub struct DecryptionShareSimple<E: PairingEngine> {
// TODO: Rename to share_index?
pub decrypter_index: usize,
pub decryption_share: E::Fqk,
pub validator_checksum: E::G1Affine,
}

impl<E: PairingEngine> DecryptionShareSimple<E> {
pub fn create(
validator_index: usize,
validator_private_key: &E::Fr,
private_key_share: &PrivateKeyShare<E>,
ciphertext: &Ciphertext<E>,
aad: &[u8],
g_inv: &E::G1Prepared,
) -> Result<DecryptionShareSimple<E>> {
check_ciphertext_validity::<E>(ciphertext, aad, g_inv)?;

// C_i = e(U, Z_i)
let decryption_share = E::pairing(
ciphertext.commitment,
private_key_share.private_key_share,
);

// C_i = dk_i^{-1} * U
let validator_checksum = ciphertext
.commitment
.mul(validator_private_key.inverse().unwrap())
.into_affine();

Ok(DecryptionShareSimple {
decrypter_index: validator_index,
decryption_share,
validator_checksum,
})
}

// TODO: Use public context (validators public state) instead of passing `validator_public_key`
// and `h` separately
pub fn verify(
&self,
share_aggregate: &E::G2Affine,
validator_public_key: &E::G2Affine,
h: &E::G2Projective,
ciphertext: &Ciphertext<E>,
) -> bool {
// D_i == e(C_i, Y_i)
if self.decryption_share
!= E::pairing(self.validator_checksum, *share_aggregate)
{
return false;
}

// e(C_i, ek_i) == e(U, H)
if E::pairing(self.validator_checksum, *validator_public_key)
!= E::pairing(ciphertext.commitment, *h)
{
return false;
}

true
}
}

// TODO: Remove this code? Currently only used in benchmarks.
pub fn batch_verify_decryption_shares<R: RngCore, E: PairingEngine>(
pub_contexts: &[PublicDecryptionContextFast<E>],
ciphertexts: &[Ciphertext<E>],
decryption_shares: &[Vec<DecryptionShareFast<E>>],
rng: &mut R,
) -> bool {
let num_ciphertexts = ciphertexts.len();
let num_shares = decryption_shares[0].len();

// Get [b_i] H for each of the decryption shares
let blinding_keys = decryption_shares[0]
.iter()
.map(|d| {
pub_contexts[d.decrypter_index]
.blinded_key_share
.blinding_key_prepared
.clone()
})
.collect::<Vec<_>>();

// For each ciphertext, generate num_shares random scalars
let alpha_ij = (0..num_ciphertexts)
.map(|_| generate_random::<_, E>(num_shares, rng))
.collect::<Vec<_>>();

let mut pairings = Vec::with_capacity(num_shares + 1);

// Compute \sum_j \alpha_{i,j} for each ciphertext i
let sum_alpha_i = alpha_ij
.iter()
.map(|alpha_j| alpha_j.iter().sum::<E::Fr>())
.collect::<Vec<_>>();

// Compute \sum_i [ \sum_j \alpha_{i,j} ] U_i
let sum_u_i = E::G1Prepared::from(
izip!(ciphertexts.iter(), sum_alpha_i.iter())
.map(|(c, alpha_j)| c.commitment.mul(*alpha_j))
.sum::<E::G1Projective>()
.into_affine(),
);

// e(\sum_i [ \sum_j \alpha_{i,j} ] U_i, -H)
pairings.push((sum_u_i, pub_contexts[0].h_inv.clone()));

let mut sum_d_i = vec![E::G1Projective::zero(); num_shares];

// sum_D_i = { [\sum_i \alpha_{i,j} ] D_i }
for (d, alpha_j) in izip!(decryption_shares.iter(), alpha_ij.iter()) {
for (sum_alpha_d_i, d_ij, alpha) in
izip!(sum_d_i.iter_mut(), d.iter(), alpha_j.iter())
{
*sum_alpha_d_i += d_ij.decryption_share.mul(*alpha);
}
}

// e([\sum_i \alpha_{i,j} ] D_i, B_i)
for (d_i, b_i) in izip!(sum_d_i.iter(), blinding_keys.iter()) {
pairings.push((E::G1Prepared::from(d_i.into_affine()), b_i.clone()));
}

E::product_of_pairings(&pairings) == E::Fqk::one()
}

// TODO: Benchmark this
@@ -79,6 +201,31 @@ pub fn verify_decryption_shares_fast<E: PairingEngine>(
true
}

pub fn verify_decryption_shares_simple<E: PairingEngine>(
pub_contexts: &Vec<PublicDecryptionContextSimple<E>>,
ciphertext: &Ciphertext<E>,
decryption_shares: &Vec<DecryptionShareSimple<E>>,
) -> bool {
let blinded_key_shares = &pub_contexts
.iter()
.map(|c| &c.blinded_key_share.blinded_key_share)
.collect::<Vec<_>>();
for (decryption_share, y_i, pub_context) in
izip!(decryption_shares, blinded_key_shares, pub_contexts)
{
let is_valid = decryption_share.verify(
y_i,
&pub_context.validator_public_key.into_affine(),
&pub_context.h.into_projective(),
ciphertext,
);
if !is_valid {
return false;
}
}
true
}

#[derive(Debug, Clone)]
pub struct DecryptionShareSimplePrecomputed<E: PairingEngine> {
pub decrypter_index: usize,
1 change: 1 addition & 0 deletions tpke/src/key_share.rs
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ pub struct PublicKeyShare<E: PairingEngine> {
pub struct BlindedKeyShare<E: PairingEngine> {
pub blinding_key: E::G2Affine, // [b] H
pub blinded_key_share: E::G2Affine, // [b] Z_{i, \omega_i}
// TODO: Should we use this kind of optizmization here or anywhere else?
pub blinding_key_prepared: E::G2Prepared,
}

94 changes: 81 additions & 13 deletions tpke/src/lib.rs
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ use subproductdomain::SubproductDomain;

use rand_core::RngCore;
use std::usize;

use thiserror::Error;

mod ciphertext;
@@ -237,7 +238,7 @@ pub fn setup_simple<E: PairingEngine>(
private_key_share: *private,
};
let b = E::Fr::rand(rng);
let blinded_key_shares = private_key_share.blind(b);
let blinded_key_share = private_key_share.blind(b);
private_contexts.push(PrivateDecryptionContextSimple::<E> {
index,
setup_params: SetupParams {
@@ -248,14 +249,17 @@ pub fn setup_simple<E: PairingEngine>(
h,
},
private_key_share,
validator_private_key: b,
public_decryption_contexts: vec![],
});
public_contexts.push(PublicDecryptionContextSimple::<E> {
domain: *domain,
public_key_share: PublicKeyShare::<E> {
public_key_share: *public,
},
blinded_key_share: blinded_key_shares,
blinded_key_share,
h,
validator_public_key: h.mul(b),
});
}
for private in private_contexts.iter_mut() {
@@ -268,14 +272,16 @@ pub fn setup_simple<E: PairingEngine>(
#[cfg(test)]
mod tests {
use crate::*;
use ark_bls12_381::Fr;

use ark_bls12_381::{Fr, G1Affine};
use ark_ec::ProjectiveCurve;
use ark_ff::BigInteger256;
use ark_std::test_rng;
use itertools::Itertools;
use rand::prelude::StdRng;
use std::ops::Mul;

type E = ark_bls12_381::Bls12_381;
type Fqk = <ark_bls12_381::Bls12_381 as PairingEngine>::Fqk;

#[test]
fn ciphertext_serialization() {
@@ -406,13 +412,11 @@ mod tests {

let (pubkey, _, contexts) =
setup_simple::<E>(threshold, shares_num, rng);
let g_inv = &contexts[0].setup_params.g_inv;
let _g_inv = &contexts[0].setup_params.g_inv;
let ciphertext = encrypt::<StdRng, E>(msg, aad, &pubkey, rng);

let bad_aad = "bad aad".as_bytes();
assert!(contexts[0]
.create_share(&ciphertext, bad_aad, g_inv)
.is_err());
assert!(contexts[0].create_share(&ciphertext, bad_aad).is_err());
}

#[test]
@@ -477,10 +481,9 @@ mod tests {

let ciphertext = encrypt::<_, E>(msg, aad, &pubkey, rng);

// Create decryption shares
let decryption_shares: Vec<_> = contexts
.iter()
.map(|c| c.create_share(&ciphertext, aad, g_inv).unwrap())
.map(|c| c.create_share(&ciphertext, aad).unwrap())
.collect();

let domain = contexts[0]
@@ -542,6 +545,67 @@ mod tests {
);
}

#[test]
fn simple_threshold_decryption_share_verification() {
let mut rng = &mut test_rng();
let shares_num = 16;
let threshold = shares_num * 2 / 3;
let msg: &[u8] = "abc".as_bytes();
let aad: &[u8] = "my-aad".as_bytes();

let (pubkey, _, contexts) =
setup_simple::<E>(threshold, shares_num, &mut rng);

let ciphertext = encrypt::<_, E>(msg, aad, &pubkey, rng);

let decryption_shares: Vec<_> = contexts
.iter()
.map(|c| c.create_share(&ciphertext, aad).unwrap())
.collect();

// In simple tDec variant, we verify decryption shares only after decryption fails.
// We could do that before, but we prefer to optimize for the happy path.

// Let's assume that combination failed here. We'll try to verify decryption shares
// against validator checksums.

// There is no share aggregation in current version of tpke (it's mocked).
// ShareEncryptions are called BlindedKeyShares.

let pub_contexts = &contexts[0].public_decryption_contexts;
assert!(verify_decryption_shares_simple(
pub_contexts,
&ciphertext,
&decryption_shares
));

// Now, let's test that verification fails if we one of the decryption shares is invalid.

let mut has_bad_checksum = decryption_shares[0].clone();
has_bad_checksum.validator_checksum = has_bad_checksum
.validator_checksum
.mul(BigInteger256::rand(rng))
.into_affine();

assert!(!has_bad_checksum.verify(
&pub_contexts[0].blinded_key_share.blinded_key_share,
&pub_contexts[0].validator_public_key.into_affine(),
&pub_contexts[0].h.into_projective(),
&ciphertext,
));

let mut has_bad_share = decryption_shares[0].clone();
has_bad_share.decryption_share =
has_bad_share.decryption_share.mul(Fqk::rand(rng));

assert!(!has_bad_share.verify(
&pub_contexts[0].blinded_key_share.blinded_key_share,
&pub_contexts[0].validator_public_key.into_affine(),
&pub_contexts[0].h.into_projective(),
&ciphertext,
));
}

#[test]
/// Ñ parties (where t <= Ñ <= N) jointly execute a "share recovery" algorithm, and the output is 1 new share.
/// The new share is intended to restore a previously existing share, e.g., due to loss or corruption.
@@ -585,11 +649,11 @@ mod tests {
contexts: &[PrivateDecryptionContextSimple<E>],
ciphertext: &Ciphertext<E>,
aad: &[u8],
g_inv: &E::G1Prepared,
_g_inv: &E::G1Prepared,
) -> E::Fqk {
let decryption_shares: Vec<_> = contexts
.iter()
.map(|c| c.create_share(ciphertext, aad, g_inv).unwrap())
.map(|c| c.create_share(ciphertext, aad).unwrap())
.collect();
make_shared_secret(
&contexts[0].public_decryption_contexts,
@@ -663,14 +727,16 @@ mod tests {
// Creating decryption shares
let mut decryption_shares: Vec<_> = remaining_participants
.iter()
.map(|c| c.create_share(&ciphertext, aad, g_inv).unwrap())
.map(|c| c.create_share(&ciphertext, aad).unwrap())
.collect();
decryption_shares.push(DecryptionShareSimple {
decrypter_index: removed_participant.index,
decryption_share: make_decryption_share(
&recovered_key_share,
&ciphertext,
),
// TODO: Implement a method to make a proper decryption share after refreshing
validator_checksum: G1Affine::zero(),
});

// Creating a shared secret from remaining shares and the recovered one
@@ -725,6 +791,8 @@ mod tests {
DecryptionShareSimple {
decrypter_index,
decryption_share,
// TODO: Implement a method to make a proper decryption share after refreshing
validator_checksum: G1Affine::zero(),
}
})
.collect();

0 comments on commit 530de97

Please sign in to comment.