Skip to content

Commit cd01f68

Browse files
tholopcopybara-github
authored andcommitted
No public description
PiperOrigin-RevId: 900569383
1 parent 2f4008f commit cd01f68

2 files changed

Lines changed: 133 additions & 5 deletions

File tree

willow/crypto/shell_parameters.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,16 +165,16 @@ pub fn create_shell_kahe_config(
165165
&& aggregation_config.max_number_of_decryptors <= 100
166166
{
167167
let packed_vector_configs =
168-
generate_packing_config(KAHE_FOR_FIXED_AHE_LOG_T_10M_10M, aggregation_config)?;
168+
generate_packing_config(KAHE_FOR_FIXED_AHE_LOG_T_100K_10M, aggregation_config)?;
169169
let kahe_total_num_coeffs: usize = packed_vector_configs
170170
.values()
171171
.map(|packed_vector_cfg| packed_vector_cfg.num_packed_coeffs as usize)
172172
.sum();
173-
let kahe_num_coeffs = 1 << KAHE_FOR_FIXED_AHE_LOG_N_10M_10M;
173+
let kahe_num_coeffs = 1 << KAHE_FOR_FIXED_AHE_LOG_N_100K_10M;
174174
return Ok(ShellKaheConfig {
175-
log_n: KAHE_FOR_FIXED_AHE_LOG_N_10M_10M,
176-
moduli: KAHE_FOR_FIXED_AHE_QS_10M_10M.to_vec(),
177-
log_t: KAHE_FOR_FIXED_AHE_LOG_T_10M_10M,
175+
log_n: KAHE_FOR_FIXED_AHE_LOG_N_100K_10M,
176+
moduli: KAHE_FOR_FIXED_AHE_QS_100K_10M.to_vec(),
177+
log_t: KAHE_FOR_FIXED_AHE_LOG_T_100K_10M,
178178
num_public_polynomials: divide_and_roundup(kahe_total_num_coeffs, kahe_num_coeffs),
179179
packed_vector_configs,
180180
});

willow/tests/willow_v1_shell.rs

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,134 @@ fn encrypt_decrypt_many_clients_decryptors() -> googletest::Result<()> {
639639
)
640640
}
641641

642+
// Helper method to run encrypt and decrypt simulation with a specific input length.
643+
fn run_encrypt_decrypt_simulation_helper(input_length: usize) -> googletest::Result<()> {
644+
const INPUT_DOMAIN: i64 = 1i64 << 30;
645+
const MAX_NUM_CLIENTS: i64 = 100_000;
646+
const MAX_NUM_DECRYPTORS: i64 = 1;
647+
const NUM_CLIENTS: usize = 3;
648+
649+
let default_id = String::from("default");
650+
let aggregation_config = generate_aggregation_config(
651+
default_id.clone(),
652+
input_length as isize,
653+
INPUT_DOMAIN,
654+
MAX_NUM_DECRYPTORS,
655+
MAX_NUM_CLIENTS,
656+
);
657+
658+
// The parameters used by `create_shell_ahe_config` below is secure for only a single
659+
// decryptor when assuming all clients are corrupted.
660+
let max_number_of_decryptors = 1;
661+
662+
// Create common KAHE/VAHE instances.
663+
let vahe = Rc::new(
664+
ShellVahe::new(create_shell_ahe_config(max_number_of_decryptors).unwrap(), CONTEXT_STRING)
665+
.unwrap(),
666+
);
667+
let kahe = Rc::new(
668+
ShellKahe::new(create_shell_kahe_config(&aggregation_config).unwrap(), CONTEXT_STRING)
669+
.unwrap(),
670+
);
671+
672+
// Create server.
673+
let server = WillowV1Server { kahe: Rc::clone(&kahe), vahe: Rc::clone(&vahe) };
674+
let mut server_state = ServerState::default();
675+
676+
// Create verifier.
677+
let verifier = WillowV1Verifier { vahe: Rc::clone(&vahe) };
678+
let mut verifier_state = VerifierState::default();
679+
680+
// Create decryptor.
681+
let mut decryptor_state = DecryptorState::default();
682+
let decryptor = WillowV1Decryptor::new_with_randomly_generated_seed(Rc::clone(&vahe)).unwrap();
683+
684+
// Decryptor generates public key share.
685+
let public_key_share = decryptor.create_public_key_share(&mut decryptor_state).unwrap();
686+
687+
// Server handles the public key share.
688+
server
689+
.handle_decryptor_public_key_share(public_key_share, "Decryptor 0", &mut server_state)
690+
.unwrap();
691+
692+
// Server creates the public key.
693+
let public_key = server.create_decryptor_public_key(&server_state).unwrap();
694+
695+
// Create clients, and each client generates their messages.
696+
let client_input_values = vec![1u64; input_length];
697+
let mut expected_output = vec![0u64; input_length];
698+
for _ in 0..NUM_CLIENTS {
699+
for i in 0..input_length {
700+
expected_output[i] += client_input_values[i];
701+
}
702+
}
703+
704+
let mut client_messages = vec![];
705+
for _ in 0..NUM_CLIENTS {
706+
let client =
707+
WillowV1Client::new_with_randomly_generated_seed(Rc::clone(&kahe), Rc::clone(&vahe))
708+
.unwrap();
709+
710+
let client_plaintext =
711+
HashMap::from([(default_id.as_str(), client_input_values.as_slice())]);
712+
let nonce = generate_random_nonce();
713+
let client_message =
714+
client.create_client_message(&client_plaintext, &public_key, &nonce).unwrap();
715+
client_messages.push(client_message);
716+
}
717+
718+
// Sort client messages by nonce.
719+
client_messages.sort_by(|a, b| a.nonce.cmp(&b.nonce));
720+
721+
// Handle client messages.
722+
for client_message in client_messages {
723+
let (ciphertext_contribution, decryption_request_contribution) =
724+
server.split_client_message(client_message).unwrap();
725+
verifier.verify_and_include(decryption_request_contribution, &mut verifier_state).unwrap();
726+
server.handle_ciphertext_contribution(ciphertext_contribution, &mut server_state).unwrap();
727+
}
728+
729+
// Verifier creates the partial decryption request.
730+
let pd_ct = verifier.create_partial_decryption_request(verifier_state).unwrap();
731+
732+
// Decryptor performs partial decryption.
733+
let pd = decryptor.handle_partial_decryption_request(pd_ct, &decryptor_state).unwrap();
734+
735+
// Server handles the partial decryption.
736+
server.handle_partial_decryption(pd, &mut server_state).unwrap();
737+
738+
// Server recovers the aggregation result.
739+
let aggregation_result = server.recover_aggregation_result(&server_state).unwrap();
740+
741+
// Check that the (padded) result matches the client plaintext.
742+
verify_that!(aggregation_result.keys().collect::<Vec<_>>(), container_eq([&default_id]))?;
743+
verify_eq!(
744+
aggregation_result.get(default_id.as_str()).unwrap()[..expected_output.len()],
745+
expected_output
746+
)
747+
}
748+
749+
/// Encrypt and decrypt with parameters that trigger `total_input_length <= 1000`.
750+
/// Reference: [shell_parameters.rs](file:///google3/third_party/secure_aggregation/willow/crypto/shell_parameters.rs)
751+
#[gtest]
752+
fn encrypt_decrypt_large_input_simulation_1k() -> googletest::Result<()> {
753+
run_encrypt_decrypt_simulation_helper(1000)
754+
}
755+
756+
/// Encrypt and decrypt with parameters that trigger `total_input_length <= 100_000`.
757+
/// Reference: [shell_parameters.rs](file:///google3/third_party/secure_aggregation/willow/crypto/shell_parameters.rs)
758+
#[gtest]
759+
fn encrypt_decrypt_large_input_simulation_100k() -> googletest::Result<()> {
760+
run_encrypt_decrypt_simulation_helper(10000)
761+
}
762+
763+
/// Encrypt and decrypt with parameters that trigger `total_input_length <= 10_000_000`.
764+
/// Reference: [shell_parameters.rs](file:///google3/third_party/secure_aggregation/willow/crypto/shell_parameters.rs)
765+
#[gtest]
766+
fn encrypt_decrypt_large_input_simulation_10m() -> googletest::Result<()> {
767+
run_encrypt_decrypt_simulation_helper(100001)
768+
}
769+
642770
// Encrypt and decrypt with multiple clients and multiple decryptors, but no dropout.
643771
#[gtest]
644772
fn encrypt_decrypt_no_dropout() -> googletest::Result<()> {

0 commit comments

Comments
 (0)