@@ -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]
644772fn encrypt_decrypt_no_dropout ( ) -> googletest:: Result < ( ) > {
0 commit comments