diff --git a/willow/benches/BUILD b/willow/benches/BUILD index ed56fc9..45a25fe 100644 --- a/willow/benches/BUILD +++ b/willow/benches/BUILD @@ -33,11 +33,13 @@ rust_library( "//willow/src/shell:single_thread_hkdf", "//willow/src/shell:vahe_shell", "//willow/src/testing_utils", + "//willow/src/traits:ahe_traits", "//willow/src/traits:client_traits", "//willow/src/traits:decryptor_traits", "//willow/src/traits:kahe_traits", "//willow/src/traits:prng_traits", "//willow/src/traits:server_traits", + "//willow/src/traits:vahe_traits", "//willow/src/traits:verifier_traits", "//willow/src/willow_v1:willow_v1_client", "//willow/src/willow_v1:willow_v1_common", diff --git a/willow/benches/shell_benchmarks.rs b/willow/benches/shell_benchmarks.rs index 9f15afd..14be3a6 100644 --- a/willow/benches/shell_benchmarks.rs +++ b/willow/benches/shell_benchmarks.rs @@ -17,16 +17,18 @@ use std::collections::HashMap; use std::hint::black_box; use std::time::Duration; +use ahe_traits::AheBase; use client_traits::SecureAggregationClient; use decryptor_traits::SecureAggregationDecryptor; use kahe_shell::ShellKahe; use kahe_traits::KaheBase; +use parameters_shell::create_shell_configs; use prng_traits::SecurePrng; use server_traits::SecureAggregationServer; -use parameters_shell::create_shell_configs; use single_thread_hkdf::SingleThreadHkdfPrng; use testing_utils::{generate_random_unsigned_vector, ShellClient, ShellClientMessage}; use vahe_shell::ShellVahe; +use vahe_traits::VaheBase; use verifier_traits::SecureAggregationVerifier; use willow_api_common::AggregationConfig; use willow_v1_client::WillowV1Client; @@ -39,6 +41,7 @@ use willow_v1_server::{ServerState, WillowV1Server}; use willow_v1_verifier::{VerifierState, WillowV1Verifier}; const DEFAULT_ID: &str = "default"; +const CONTEXT_STRING: &[u8] = b"benchmark_context_string"; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] @@ -126,12 +129,11 @@ fn setup_base(args: &Args) -> BaseInputs { }; let (kahe_config, ahe_config) = create_shell_configs(&aggregation_config).unwrap(); let public_kahe_seed = SingleThreadHkdfPrng::generate_seed().unwrap(); - let public_ahe_seed = SingleThreadHkdfPrng::generate_seed().unwrap(); // Create client. let common = WillowCommon { - kahe: ShellKahe::new(kahe_config.clone(), &public_kahe_seed).unwrap(), - vahe: ShellVahe::new(ahe_config.clone(), &public_ahe_seed).unwrap(), + kahe: ShellKahe::new(kahe_config.clone(), CONTEXT_STRING).unwrap(), + vahe: ShellVahe::new(ahe_config.clone(), CONTEXT_STRING).unwrap(), }; let seed = SingleThreadHkdfPrng::generate_seed().unwrap(); let prng = SingleThreadHkdfPrng::create(&seed).unwrap(); @@ -139,8 +141,8 @@ fn setup_base(args: &Args) -> BaseInputs { // Create decryptor, which needs its own `common` and `prng`. let common = WillowCommon { - kahe: ShellKahe::new(kahe_config.clone(), &public_kahe_seed).unwrap(), - vahe: ShellVahe::new(ahe_config.clone(), &public_ahe_seed).unwrap(), + kahe: ShellKahe::new(kahe_config.clone(), CONTEXT_STRING).unwrap(), + vahe: ShellVahe::new(ahe_config.clone(), CONTEXT_STRING).unwrap(), }; let seed = SingleThreadHkdfPrng::generate_seed().unwrap(); let prng = SingleThreadHkdfPrng::create(&seed).unwrap(); @@ -149,16 +151,16 @@ fn setup_base(args: &Args) -> BaseInputs { // Create server. let common = WillowCommon { - kahe: ShellKahe::new(kahe_config.clone(), &public_kahe_seed).unwrap(), - vahe: ShellVahe::new(ahe_config.clone(), &public_ahe_seed).unwrap(), + kahe: ShellKahe::new(kahe_config.clone(), CONTEXT_STRING).unwrap(), + vahe: ShellVahe::new(ahe_config.clone(), CONTEXT_STRING).unwrap(), }; let server = WillowV1Server { common }; let mut server_state = ServerState::new(); // Create verifier. let common = WillowCommon { - kahe: ShellKahe::new(kahe_config.clone(), &public_kahe_seed).unwrap(), - vahe: ShellVahe::new(ahe_config.clone(), &public_ahe_seed).unwrap(), + kahe: ShellKahe::new(kahe_config.clone(), CONTEXT_STRING).unwrap(), + vahe: ShellVahe::new(ahe_config.clone(), CONTEXT_STRING).unwrap(), }; let verifier = WillowV1Verifier { common }; let verifier_state = VerifierState::new(); diff --git a/willow/src/shell/ahe.rs b/willow/src/shell/ahe.rs index 3680558..9ab6894 100644 --- a/willow/src/shell/ahe.rs +++ b/willow/src/shell/ahe.rs @@ -56,21 +56,6 @@ pub struct ShellAhe { } impl ShellAhe { - pub fn new(config: ShellAheConfig, public_seed: &Seed) -> Result { - let num_coeffs = 1 << config.log_n; - let public_ahe_parameters = ahe::create_public_parameters( - config.log_n, - config.t, - &config.qs, - /* error_variance= */ ERROR_VARIANCE, - /* s_base_flood= */ S_BASE_FLOOD, - config.s_flood, - &public_seed, - )?; - - Ok(Self { public_ahe_parameters, num_coeffs }) - } - /// Convenience function. fn add_vec_rns_polynomial_in_place( &self, @@ -400,6 +385,29 @@ impl AheBase for ShellAhe { type Rng = SingleThreadHkdfPrng; + type Config = ShellAheConfig; + + fn new(config: Self::Config, context_string: &[u8]) -> Result { + let num_coeffs = 1 << config.log_n; + let public_seed = single_thread_hkdf::compute_hkdf( + context_string, + b"", + b"ShellAhe.public_seed", + single_thread_hkdf::seed_length(), + )?; + let public_ahe_parameters = ahe::create_public_parameters( + config.log_n, + config.t, + &config.qs, + /* error_variance= */ ERROR_VARIANCE, + /* s_base_flood= */ S_BASE_FLOOD, + config.s_flood, + &public_seed, + )?; + + Ok(Self { public_ahe_parameters, num_coeffs }) + } + fn aggregate_public_key_shares( &self, public_key_shares: &[Self::PublicKeyShare], @@ -651,13 +659,13 @@ mod test { const NUM_DECRYPTORS: usize = 3; const NUM_CLIENTS: usize = 1000; const MAX_ABSOLUTE_VALUE: i64 = 72; + const CONTEXT_STRING: &[u8] = b"test_context_string"; #[gtest] fn test_encrypt_decrypt_one() -> googletest::Result<()> { const NUM_VALUES: usize = 100; - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let ahe = ShellAhe::new(make_ahe_config(), &public_seed)?; + let ahe = ShellAhe::new(make_ahe_config(), CONTEXT_STRING)?; let pt = vec![1, 2, 3, 4, 5, 6, 7, 8]; let seed = SingleThreadHkdfPrng::generate_seed()?; @@ -682,8 +690,7 @@ mod test { let config = make_ahe_config(); let t = config.t; // Keep a copy of the plaintext modulus. - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let ahe = ShellAhe::new(config, &public_seed)?; + let ahe = ShellAhe::new(config, CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; @@ -750,8 +757,7 @@ mod test { #[gtest] fn test_errors() -> googletest::Result<()> { - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let ahe = ShellAhe::new(make_ahe_config(), &public_seed)?; + let ahe = ShellAhe::new(make_ahe_config(), CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; @@ -826,11 +832,10 @@ mod test { #[gtest] fn test_manual_encryption() -> googletest::Result<()> { - let public_seed = SingleThreadHkdfPrng::generate_seed()?; let config = make_ahe_config(); let q: i128 = config.qs.iter().map(|x| *x as i128).product(); - let ahe = ShellAhe::new(config, &public_seed)?; + let ahe = ShellAhe::new(config, CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; let (_, pk_share, _) = ahe.key_gen(&mut prng)?; @@ -871,9 +876,8 @@ mod test { #[gtest] fn test_export_ciphertext_has_right_order() -> googletest::Result<()> { - let public_seed = SingleThreadHkdfPrng::generate_seed()?; let config = make_ahe_config(); - let ahe = ShellAhe::new(config, &public_seed)?; + let ahe = ShellAhe::new(config, CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; let (_, pk_share, _) = ahe.key_gen(&mut prng)?; diff --git a/willow/src/shell/kahe.rs b/willow/src/shell/kahe.rs index cacbb92..a8a1153 100644 --- a/willow/src/shell/kahe.rs +++ b/willow/src/shell/kahe.rs @@ -50,22 +50,6 @@ pub struct ShellKahe { } impl ShellKahe { - pub fn new( - shell_kahe_config: ShellKaheConfig, - public_seed: &Seed, - ) -> Result { - Self::validate_kahe_config(&shell_kahe_config)?; - let num_coeffs = 1 << shell_kahe_config.log_n; - let public_kahe_parameters = kahe::create_public_parameters( - shell_kahe_config.log_n as u64, - shell_kahe_config.log_t as u64, - &shell_kahe_config.moduli, - shell_kahe_config.num_public_polynomials, - &public_seed, - )?; - Ok(Self { config: shell_kahe_config, num_coeffs, public_kahe_parameters }) - } - /// Validates KAHE parameters in ShellKaheConfig. fn validate_kahe_config(config: &ShellKaheConfig) -> Result<(), status::StatusError> { if config.log_t > BIG_INT_BITS { @@ -113,6 +97,30 @@ impl KaheBase for ShellKahe { type Rng = SingleThreadHkdfPrng; + type Config = ShellKaheConfig; + + fn new( + shell_kahe_config: Self::Config, + context_string: &[u8], + ) -> Result { + Self::validate_kahe_config(&shell_kahe_config)?; + let num_coeffs = 1 << shell_kahe_config.log_n; + let public_seed = single_thread_hkdf::compute_hkdf( + context_string, + b"", + b"ShellKahe.public_seed", + single_thread_hkdf::seed_length(), + )?; + let public_kahe_parameters = kahe::create_public_parameters( + shell_kahe_config.log_n as u64, + shell_kahe_config.log_t as u64, + &shell_kahe_config.moduli, + shell_kahe_config.num_public_polynomials, + &public_seed, + )?; + Ok(Self { config: shell_kahe_config, num_coeffs, public_kahe_parameters }) + } + fn add_keys_in_place( &self, left: &Self::SecretKey, @@ -299,6 +307,8 @@ mod test { /// Default ID used in tests. const DEFAULT_ID: &str = "default"; + const CONTEXT_STRING: &[u8] = b"test_context_string"; + #[gtest] fn test_encrypt_decrypt_short() -> googletest::Result<()> { let plaintext_modulus_bits = 39; @@ -307,8 +317,7 @@ mod test { PackedVectorConfig { base: 10, dimension: 2, num_packed_coeffs: 5 }, )]); let kahe_config = make_kahe_config_for(plaintext_modulus_bits, packed_vector_configs)?; - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let kahe = ShellKahe::new(kahe_config, &public_seed)?; + let kahe = ShellKahe::new(kahe_config, CONTEXT_STRING)?; let pt = HashMap::from([(String::from(DEFAULT_ID), vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])]); let seed = SingleThreadHkdfPrng::generate_seed()?; @@ -327,8 +336,7 @@ mod test { PackedVectorConfig { base: 10, dimension: 2, num_packed_coeffs: 5 }, )]); let kahe_config = make_kahe_config_for(plaintext_modulus_bits, packed_vector_configs)?; - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let kahe = ShellKahe::new(kahe_config, &public_seed)?; + let kahe = ShellKahe::new(kahe_config, CONTEXT_STRING)?; let pt = HashMap::from([(String::from(DEFAULT_ID), vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])]); let seed = SingleThreadHkdfPrng::generate_seed()?; @@ -364,8 +372,7 @@ mod test { packed_vector_config.num_packed_coeffs = num_messages; set_kahe_num_public_polynomials(&mut kahe_config); - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let kahe = ShellKahe::new(kahe_config, &public_seed)?; + let kahe = ShellKahe::new(kahe_config, CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; @@ -397,8 +404,7 @@ mod test { )]); let kahe_config = make_kahe_config_for(plaintext_modulus_bits, packed_vector_configs)?; - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let kahe = ShellKahe::new(kahe_config, &public_seed)?; + let kahe = ShellKahe::new(kahe_config, CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; @@ -434,8 +440,7 @@ mod test { let packed_vector_configs = HashMap::from([]); let kahe_config = make_kahe_config_for(plaintext_modulus_bits, packed_vector_configs)?; - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let kahe = ShellKahe::new(kahe_config, &public_seed)?; + let kahe = ShellKahe::new(kahe_config, CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; @@ -477,8 +482,7 @@ mod test { let plaintext_modulus_bits = 39; let packed_vector_configs = HashMap::from([]); let kahe_config = make_kahe_config_for(plaintext_modulus_bits, packed_vector_configs)?; - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let kahe = ShellKahe::new(kahe_config, &public_seed)?; + let kahe = ShellKahe::new(kahe_config, CONTEXT_STRING)?; // The seed used to sample the secret keys. let seed = SingleThreadHkdfPrng::generate_seed()?; diff --git a/willow/src/shell/vahe.rs b/willow/src/shell/vahe.rs index 0dbe408..72a45be 100644 --- a/willow/src/shell/vahe.rs +++ b/willow/src/shell/vahe.rs @@ -37,16 +37,6 @@ pub struct ShellVahe { } impl ShellVahe { - // The public_seed is assumed to be a uniform 16-byte slice. - pub fn new(config: ShellAheConfig, public_seed: &Seed) -> Result { - let mut q = 1; - for modulus in &config.qs { - q *= *modulus as u128; - } - let ahe = ShellAhe::new(config, public_seed)?; - Ok(ShellVahe { ahe: ahe, q: q, public_seed: public_seed.clone() }) - } - fn get_transcript_and_proof_seed( &self, operation_name: &'static [u8], @@ -78,6 +68,22 @@ impl AheBase for ShellVahe { type PartialDecryption = ::PartialDecryption; type PublicKey = ::PublicKey; type Rng = ::Rng; + type Config = ShellAheConfig; + + fn new(config: Self::Config, context_string: &[u8]) -> Result { + let public_seed = single_thread_hkdf::compute_hkdf( + context_string, + b"", + b"ShellVahe.public_seed", + single_thread_hkdf::seed_length(), + )?; + let mut q = 1; + for modulus in &config.qs { + q *= *modulus as u128; + } + let ahe = ShellAhe::new(config, context_string)?; + Ok(ShellVahe { ahe: ahe, q: q, public_seed: public_seed }) + } fn aggregate_public_key_shares( &self, @@ -392,10 +398,11 @@ mod test { use shell_testing_parameters::make_ahe_config; use single_thread_hkdf::SingleThreadHkdfPrng; + const CONTEXT_STRING: &[u8] = b"testing_context_string"; + #[gtest] fn test_verifiable_key_gen() -> googletest::Result<()> { - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let vahe = ShellVahe::new(make_ahe_config(), &public_seed)?; + let vahe = ShellVahe::new(make_ahe_config(), CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; let (_, pk_share, key_gen_proof) = vahe.verifiable_key_gen(&mut prng)?; @@ -405,8 +412,7 @@ mod test { #[gtest] fn test_verifiable_key_gen_with_bad_proof() -> googletest::Result<()> { - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let vahe = ShellVahe::new(make_ahe_config(), &public_seed)?; + let vahe = ShellVahe::new(make_ahe_config(), CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; let (_, pk_share, _) = vahe.verifiable_key_gen(&mut prng)?; @@ -419,8 +425,7 @@ mod test { #[gtest] fn test_verifiable_encrypt() -> googletest::Result<()> { - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let vahe = ShellVahe::new(make_ahe_config(), &public_seed)?; + let vahe = ShellVahe::new(make_ahe_config(), CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; let (_, pk_share, _) = vahe.verifiable_key_gen(&mut prng)?; @@ -432,8 +437,7 @@ mod test { #[gtest] fn test_verifiable_encrypt_long_plaintext() -> googletest::Result<()> { - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let vahe = ShellVahe::new(make_ahe_config(), &public_seed)?; + let vahe = ShellVahe::new(make_ahe_config(), CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; let (_, pk_share, _) = vahe.verifiable_key_gen(&mut prng)?; @@ -445,8 +449,7 @@ mod test { #[gtest] fn test_verifiable_encrypt_with_bad_length_proof() -> googletest::Result<()> { - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let vahe = ShellVahe::new(make_ahe_config(), &public_seed)?; + let vahe = ShellVahe::new(make_ahe_config(), CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; let (_, pk_share, key_gen_proof) = vahe.verifiable_key_gen(&mut prng)?; @@ -460,8 +463,7 @@ mod test { #[gtest] fn test_verifiable_encrypt_with_bad_proof() -> googletest::Result<()> { - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let vahe = ShellVahe::new(make_ahe_config(), &public_seed)?; + let vahe = ShellVahe::new(make_ahe_config(), CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; let (_, pk_share, key_gen_proof) = vahe.verifiable_key_gen(&mut prng)?; @@ -475,8 +477,7 @@ mod test { #[gtest] fn test_verifiable_partial_dec() -> googletest::Result<()> { - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let vahe = ShellVahe::new(make_ahe_config(), &public_seed)?; + let vahe = ShellVahe::new(make_ahe_config(), CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; let (sk_share, pk_share, _) = vahe.verifiable_key_gen(&mut prng)?; @@ -490,8 +491,7 @@ mod test { #[gtest] fn test_verifiable_partial_dec_long_plaintext() -> googletest::Result<()> { - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let vahe = ShellVahe::new(make_ahe_config(), &public_seed)?; + let vahe = ShellVahe::new(make_ahe_config(), CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; let (sk_share, pk_share, _) = vahe.verifiable_key_gen(&mut prng)?; @@ -505,8 +505,7 @@ mod test { #[gtest] fn test_verifiable_partial_dec_with_bad_length_proof() -> googletest::Result<()> { - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let vahe = ShellVahe::new(make_ahe_config(), &public_seed)?; + let vahe = ShellVahe::new(make_ahe_config(), CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; let (sk_share, pk_share, key_gen_proof) = vahe.verifiable_key_gen(&mut prng)?; @@ -522,8 +521,7 @@ mod test { #[gtest] fn test_verifiable_partial_dec_with_bad_proof() -> googletest::Result<()> { - let public_seed = SingleThreadHkdfPrng::generate_seed()?; - let vahe = ShellVahe::new(make_ahe_config(), &public_seed)?; + let vahe = ShellVahe::new(make_ahe_config(), CONTEXT_STRING)?; let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; let (sk_share, pk_share, key_gen_proof) = vahe.verifiable_key_gen(&mut prng)?; diff --git a/willow/src/testing_utils/testing_utils.rs b/willow/src/testing_utils/testing_utils.rs index 8c953a9..479b991 100644 --- a/willow/src/testing_utils/testing_utils.rs +++ b/willow/src/testing_utils/testing_utils.rs @@ -45,11 +45,10 @@ pub fn generate_random_signed_vector(num_values: usize, max_absolute_value: i64) /// and the given public seeds. pub fn create_willow_common( aggregation_config: &AggregationConfig, - public_kahe_seed: &Seed, - public_ahe_seed: &Seed, + context_string: &[u8], ) -> WillowCommon { - let kahe = ShellKahe::new(make_kahe_config(aggregation_config), public_kahe_seed).unwrap(); - let vahe = ShellVahe::new(make_ahe_config(), public_ahe_seed).unwrap(); + let kahe = ShellKahe::new(make_kahe_config(aggregation_config), context_string).unwrap(); + let vahe = ShellVahe::new(make_ahe_config(), context_string).unwrap(); WillowCommon { kahe, vahe } } diff --git a/willow/src/traits/ahe.rs b/willow/src/traits/ahe.rs index 31e3c73..9ff68a5 100644 --- a/willow/src/traits/ahe.rs +++ b/willow/src/traits/ahe.rs @@ -16,7 +16,13 @@ use status::StatusError; /// Base trait for (Asymmetric) multiparty Additive Homomorphic Encryption (AHE) /// schemes. Mostly contains types that are shared across all roles. -pub trait AheBase { +pub trait AheBase: Sized { + type Config; + + /// Creates an AHE instance. `context_string` is used for domain separation and must be unique + /// to each instantiation of the AHE scheme. + fn new(config: Self::Config, context_string: &[u8]) -> Result; + /// Secret key share. type SecretKeyShare; diff --git a/willow/src/traits/kahe.rs b/willow/src/traits/kahe.rs index ff8efb4..c50ef64 100644 --- a/willow/src/traits/kahe.rs +++ b/willow/src/traits/kahe.rs @@ -18,7 +18,13 @@ use status::StatusError; /// Base trait for KAHE primitives, containing types that are shared across all /// primitives. Types implementing this trait can also store public parameters /// shared across primitives. -pub trait KaheBase { +pub trait KaheBase: Sized { + type Config; + + /// Creates a KAHE instance. `context_string` is used for domain separation and must be unique + /// to each instantiation of the KAHE scheme. + fn new(config: Self::Config, context_string: &[u8]) -> Result; + /// Secret key for symmetric encryption. Supports addition (key /// homomorphism). Addition needs additional context and works on /// types defined outside this crate, so we use functions instead of diff --git a/willow/src/traits/vahe.rs b/willow/src/traits/vahe.rs index 72a9bc0..e827dd9 100644 --- a/willow/src/traits/vahe.rs +++ b/willow/src/traits/vahe.rs @@ -15,7 +15,7 @@ use ahe_traits::AheBase; use status::{Status, StatusError}; -pub trait VaheBase: AheBase { +pub trait VaheBase: AheBase + Sized { type KeyGenProof; type EncryptionProof: Clone; type PartialDecProof; diff --git a/willow/src/willow_v1/client.rs b/willow/src/willow_v1/client.rs index c197eb7..3b53f49 100644 --- a/willow/src/willow_v1/client.rs +++ b/willow/src/willow_v1/client.rs @@ -76,6 +76,8 @@ mod test { use vahe_traits::{Recover, VaheBase}; use willow_api_common::AggregationConfig; + const CONTEXT_STRING: &[u8] = b"test_context_string"; + #[gtest] fn test_create_client_message() -> googletest::Result<()> { let default_id = String::from("default"); @@ -89,16 +91,15 @@ mod test { }; // Generate public parameters for KAHE and AHE. let public_kahe_seed = SingleThreadHkdfPrng::generate_seed()?; - let public_ahe_seed = SingleThreadHkdfPrng::generate_seed()?; // Create a client. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let client_seed = SingleThreadHkdfPrng::generate_seed()?; let prng = SingleThreadHkdfPrng::create(&client_seed)?; let mut client = WillowV1Client { common: common, prng: prng }; // Generate AHE keys. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; let (sk_share, pk_share, _) = common.vahe.key_gen(&mut prng)?; @@ -146,22 +147,21 @@ mod test { // Generate public parameters for KAHE and AHE. let public_kahe_seed = SingleThreadHkdfPrng::generate_seed()?; - let public_ahe_seed = SingleThreadHkdfPrng::generate_seed()?; // Create a client. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let client1_seed = SingleThreadHkdfPrng::generate_seed()?; let prng = SingleThreadHkdfPrng::create(&client1_seed)?; let mut client1 = WillowV1Client { common: common, prng: prng }; // Create a second client. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let client2_seed = SingleThreadHkdfPrng::generate_seed()?; let prng = SingleThreadHkdfPrng::create(&client2_seed)?; let mut client2 = WillowV1Client { common: common, prng: prng }; // Generate AHE keys. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let seed = SingleThreadHkdfPrng::generate_seed()?; let mut prng = SingleThreadHkdfPrng::create(&seed)?; let (sk_share, pk_share, _) = common.vahe.key_gen(&mut prng)?; diff --git a/willow/src/willow_v1/common.rs b/willow/src/willow_v1/common.rs index 86d4637..5b11144 100644 --- a/willow/src/willow_v1/common.rs +++ b/willow/src/willow_v1/common.rs @@ -65,6 +65,7 @@ pub struct CiphertextContribution { pub struct DecryptionRequestContribution { pub partial_dec_ciphertext: Vahe::PartialDecCiphertext, pub proof: Vahe::EncryptionProof, + // pub client_id: u128, } impl SecureAggregationCommon for WillowCommon { diff --git a/willow/tests/BUILD b/willow/tests/BUILD index 78239d9..2014077 100644 --- a/willow/tests/BUILD +++ b/willow/tests/BUILD @@ -41,6 +41,7 @@ rust_test( "//willow/src/traits:kahe_traits", "//willow/src/traits:prng_traits", "//willow/src/traits:server_traits", + "//willow/src/traits:vahe_traits", "//willow/src/traits:verifier_traits", "//willow/src/willow_v1:willow_v1_client", "//willow/src/willow_v1:willow_v1_common", @@ -49,23 +50,3 @@ rust_test( "//willow/src/willow_v1:willow_v1_verifier", ], ) - -# Dummy KAHE test. -rust_library( - name = "dummy_kahe", - testonly = 1, - srcs = ["dummy_kahe.rs"], - deps = [ - "//shell_wrapper:status", - "//willow/src/traits:kahe_traits", - ], -) - -rust_test( - name = "dummy_kahe_test", - crate = ":dummy_kahe", - deps = [ - "@crate_index//:googletest", - "//shell_wrapper:status_matchers", - ], -) diff --git a/willow/tests/dummy_kahe.rs b/willow/tests/dummy_kahe.rs deleted file mode 100644 index 943794a..0000000 --- a/willow/tests/dummy_kahe.rs +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use kahe_traits::{KaheBase, KaheDecrypt, KaheEncrypt, KaheKeygen}; -use std::ops::AddAssign; - -/// A placeholder type for keys, plaintexts and ciphertexts. -#[derive(Default, Debug, PartialEq)] -pub struct Poly(Vec); // Wrapper around Vec to implement our own AddAssign. - -/// Add two polynomials coordinate-wise. -impl AddAssign<&Self> for Poly { - fn add_assign(&mut self, rhs: &Self) { - for (i, v) in rhs.0.iter().enumerate() { - self.0[i] += v; - } - } -} - -/// Base type holding data shared by all Dummy KAHE roles. -#[derive(Default)] -pub struct DummyKahe { - a: Poly, // public *a*, same for all roles. -} - -impl DummyKahe { - /// Setup function that samples *a* from a seed. - pub fn setup(seed: &[u8; 32]) -> Self { - let a = Poly(vec![seed[0]]); // Could be a PRG - DummyKahe { a } - } -} - -/// Associated types for DummyKahe. -impl KaheBase for DummyKahe { - type SecretKey = Poly; - type Plaintext = Poly; - type Ciphertext = Poly; - type Rng = Vec; - - fn add_keys_in_place(&self, left: &Poly, right: &mut Poly) -> status::Status { - *right += left; - Ok(()) - } - - fn add_plaintexts_in_place(&self, left: &Poly, right: &mut Poly) -> status::Status { - *right += left; - Ok(()) - } - - fn add_ciphertexts_in_place(&self, left: &Poly, right: &mut Poly) -> status::Status { - *right += left; - Ok(()) - } -} - -impl KaheKeygen for DummyKahe { - fn key_gen(&self, r: &mut Self::Rng) -> Result { - Ok(Poly(vec![r[0]])) - } -} - -impl KaheEncrypt for DummyKahe { - /// Encrypt as identity. - fn encrypt( - &self, - plaintext: &Self::Plaintext, - _: &Self::SecretKey, - _: &mut Self::Rng, - ) -> Result { - let _ = &self.a.0; // We could use *a* here. - Ok(Poly(plaintext.0.to_vec())) // Allocate a new vec with identical elements. - } -} - -impl KaheDecrypt for DummyKahe { - /// Decrypt as identity. - fn decrypt( - &self, - ciphertext: &Self::Ciphertext, - _: &Self::SecretKey, - ) -> Result { - Ok(Poly(ciphertext.0.to_vec())) - } -} - -#[cfg(test)] -mod test { - use super::*; - - use googletest::{gtest, verify_eq, verify_that}; - - /// Test that sum is implemented correctly. - #[gtest] - fn sum() -> googletest::Result<()> { - let mut a = Poly(vec![1, 2, 3]); - let b = Poly(vec![4, 5, 6]); - a += &b; - verify_eq!(a.0, vec![5, 7, 9]) - } - - /// Check that a single input is encrypted and decrypted correctly. - #[gtest] - fn single_input() -> googletest::Result<()> { - // This test maintains the state of everyone. In the binaries, some - // functions will be called by the client and some by the server, - // and each role will persist some state to pass the right arguments. - - // Both Client and Server would run this on their side. - let seed = [0u8; 32]; - let dummy_kahe = DummyKahe::setup(&seed); - - // Client generates key and encrypts message. - let mut rng = vec![0u8]; - let sk = dummy_kahe.key_gen(&mut rng)?; - let plaintext = Poly(vec![1, 2, 3]); - let ciphertext = dummy_kahe.encrypt(&plaintext, &sk, &mut rng)?; - - // Server receives ciphertext and decrypts. - // (In reality there will be multiple inputs) - let decrypted = dummy_kahe.decrypt(&ciphertext, &sk)?; - verify_eq!(plaintext, decrypted) - } - - /// Check homomorphic addition of two inputs. - #[gtest] - fn add_two_inputs() -> googletest::Result<()> { - let seed = [0u8; 32]; - let dummy_kahe = DummyKahe::setup(&seed); - - // Client 1 - let mut rng1 = vec![0u8]; - let sk1 = dummy_kahe.key_gen(&mut rng1)?; - let pt1 = Poly(vec![1, 2, 3]); - let ct1 = dummy_kahe.encrypt(&pt1, &sk1, &mut rng1)?; - - // Client 2 - let mut rng2 = vec![0u8]; - let mut sk2 = dummy_kahe.key_gen(&mut rng2)?; - let mut pt2 = Poly(vec![4, 5, 6]); - let mut ct2 = dummy_kahe.encrypt(&pt2, &sk2, &mut rng2)?; - - // Decryptor adds up keys - dummy_kahe.add_keys_in_place(&sk1, &mut sk2)?; - - // Server adds ciphertexts and uses aggregated key to decrypt. - dummy_kahe.add_ciphertexts_in_place(&ct1, &mut ct2)?; - let pt_sum = dummy_kahe.decrypt(&ct2, &sk2)?; - dummy_kahe.add_plaintexts_in_place(&pt1, &mut pt2)?; - verify_eq!(pt2, pt_sum) - } -} diff --git a/willow/tests/willow_v1_shell.rs b/willow/tests/willow_v1_shell.rs index e740c7c..d972f1d 100644 --- a/willow/tests/willow_v1_shell.rs +++ b/willow/tests/willow_v1_shell.rs @@ -12,11 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +use ahe_traits::AheBase; use client_traits::SecureAggregationClient; use decryptor_traits::SecureAggregationDecryptor; use googletest::prelude::container_eq; use googletest::{gtest, verify_eq, verify_that}; use kahe_shell::ShellKahe; +use kahe_traits::KaheBase; use parameters_shell::create_shell_configs; use prng_traits::SecurePrng; use server_traits::SecureAggregationServer; @@ -26,6 +28,7 @@ use status_matchers_rs::status_is; use std::collections::HashMap; use testing_utils::{create_willow_common, generate_random_unsigned_vector}; use vahe_shell::ShellVahe; +use vahe_traits::VaheBase; use verifier_traits::SecureAggregationVerifier; use willow_api_common::AggregationConfig; use willow_v1_client::WillowV1Client; @@ -34,6 +37,8 @@ use willow_v1_decryptor::{DecryptorState, WillowV1Decryptor}; use willow_v1_server::{ServerState, WillowV1Server}; use willow_v1_verifier::{VerifierState, WillowV1Verifier}; +const CONTEXT_STRING: &[u8] = b"testing_context_string"; + /// Generates an AggregationConfig for test cases in this file. fn generate_aggregation_config( vector_id: String, @@ -58,29 +63,28 @@ fn encrypt_decrypt_one() -> googletest::Result<()> { let default_id = String::from("default"); let aggregation_config = generate_aggregation_config(default_id.clone(), 16, 10, 1, 1); let public_kahe_seed = SingleThreadHkdfPrng::generate_seed().unwrap(); - let public_ahe_seed = SingleThreadHkdfPrng::generate_seed().unwrap(); // Create client. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let seed = SingleThreadHkdfPrng::generate_seed().unwrap(); let prng = SingleThreadHkdfPrng::create(&seed).unwrap(); let mut client = WillowV1Client { common, prng }; // Create decryptor, which needs its own `common` (with same public polynomials // generated from the seeds) and `prng`. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let seed = SingleThreadHkdfPrng::generate_seed().unwrap(); let prng = SingleThreadHkdfPrng::create(&seed).unwrap(); let mut decryptor_state = DecryptorState::new(); let mut decryptor = WillowV1Decryptor { common, prng }; // Create server. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let server = WillowV1Server { common }; let mut server_state = ServerState::new(); // Create verifier. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let verifier = WillowV1Verifier { common }; let mut verifier_state = VerifierState::new(); @@ -134,12 +138,11 @@ fn encrypt_decrypt_multiple_clients() -> googletest::Result<()> { generate_aggregation_config(default_id.clone(), 16, 10, 1, NUM_CLIENTS); let public_kahe_seed = SingleThreadHkdfPrng::generate_seed().unwrap(); - let public_ahe_seed = SingleThreadHkdfPrng::generate_seed().unwrap(); // Create clients. let mut clients = vec![]; for _ in 0..NUM_CLIENTS { - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let seed = SingleThreadHkdfPrng::generate_seed().unwrap(); let prng = SingleThreadHkdfPrng::create(&seed).unwrap(); let client = WillowV1Client { common, prng }; @@ -148,19 +151,19 @@ fn encrypt_decrypt_multiple_clients() -> googletest::Result<()> { // Create decryptor, which needs its own `common` (with same public polynomials // generated from the seeds) and `prng`. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let seed = SingleThreadHkdfPrng::generate_seed().unwrap(); let prng = SingleThreadHkdfPrng::create(&seed).unwrap(); let mut decryptor_state = DecryptorState::new(); let mut decryptor = WillowV1Decryptor { common, prng }; // Create server. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let server = WillowV1Server { common }; let mut server_state = ServerState::new(); // Create verifier. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let verifier = WillowV1Verifier { common }; let mut verifier_state = VerifierState::new(); @@ -219,12 +222,11 @@ fn encrypt_decrypt_multiple_clients_including_invalid_proofs() -> googletest::Re let aggregation_config = generate_aggregation_config(default_id.clone(), 16, 10, 1, NUM_MAX_CLIENTS); let public_kahe_seed = SingleThreadHkdfPrng::generate_seed().unwrap(); - let public_ahe_seed = SingleThreadHkdfPrng::generate_seed().unwrap(); // Create clients. let mut good_clients = vec![]; for _ in 0..NUM_GOOD_CLIENTS { - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let seed = SingleThreadHkdfPrng::generate_seed().unwrap(); let prng = SingleThreadHkdfPrng::create(&seed).unwrap(); let client = WillowV1Client { common, prng }; @@ -234,7 +236,7 @@ fn encrypt_decrypt_multiple_clients_including_invalid_proofs() -> googletest::Re // Create bad clients. let mut bad_clients = vec![]; for _ in 0..NUM_BAD_CLIENTS { - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let seed = SingleThreadHkdfPrng::generate_seed().unwrap(); let prng = SingleThreadHkdfPrng::create(&seed).unwrap(); let client = WillowV1Client { common, prng }; @@ -243,19 +245,19 @@ fn encrypt_decrypt_multiple_clients_including_invalid_proofs() -> googletest::Re // Create decryptor, which needs its own `common` (with same public polynomials // generated from the seeds) and `prng`. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let seed = SingleThreadHkdfPrng::generate_seed().unwrap(); let prng = SingleThreadHkdfPrng::create(&seed).unwrap(); let mut decryptor_state = DecryptorState::new(); let mut decryptor = WillowV1Decryptor { common, prng }; // Create server. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let server = WillowV1Server { common }; let mut server_state = ServerState::new(); // Create verifier. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let verifier = WillowV1Verifier { common }; let mut verifier_state = VerifierState::new(); @@ -352,20 +354,19 @@ fn encrypt_decrypt_many_clients_decryptors() -> googletest::Result<()> { // Create the public seeds for all clients, decryptors, and server. let public_kahe_seed = SingleThreadHkdfPrng::generate_seed().unwrap(); - let public_ahe_seed = SingleThreadHkdfPrng::generate_seed().unwrap(); // Create server. let (kahe_config, ahe_config) = create_shell_configs(&aggregation_config).unwrap(); - let kahe = ShellKahe::new(kahe_config, &public_kahe_seed).unwrap(); - let vahe = ShellVahe::new(ahe_config, &public_ahe_seed).unwrap(); + let kahe = ShellKahe::new(kahe_config, CONTEXT_STRING).unwrap(); + let vahe = ShellVahe::new(ahe_config, CONTEXT_STRING).unwrap(); let common = WillowCommon { kahe, vahe }; let server = WillowV1Server { common }; let mut server_state = ServerState::new(); // Create verifier. let (kahe_config, ahe_config) = create_shell_configs(&aggregation_config).unwrap(); - let kahe = ShellKahe::new(kahe_config, &public_kahe_seed).unwrap(); - let vahe = ShellVahe::new(ahe_config, &public_ahe_seed).unwrap(); + let kahe = ShellKahe::new(kahe_config, CONTEXT_STRING).unwrap(); + let vahe = ShellVahe::new(ahe_config, CONTEXT_STRING).unwrap(); let common = WillowCommon { kahe, vahe }; let verifier = WillowV1Verifier { common }; let mut verifier_state = VerifierState::new(); @@ -376,8 +377,8 @@ fn encrypt_decrypt_many_clients_decryptors() -> googletest::Result<()> { let mut decryptor_states = vec![]; for _ in 0..NUM_DECRYPTORS { let (kahe_config, ahe_config) = create_shell_configs(&aggregation_config).unwrap(); - let kahe = ShellKahe::new(kahe_config, &public_kahe_seed).unwrap(); - let vahe = ShellVahe::new(ahe_config, &public_ahe_seed).unwrap(); + let kahe = ShellKahe::new(kahe_config, CONTEXT_STRING).unwrap(); + let vahe = ShellVahe::new(ahe_config, CONTEXT_STRING).unwrap(); let common = WillowCommon { kahe, vahe }; let seed = SingleThreadHkdfPrng::generate_seed().unwrap(); let prng = SingleThreadHkdfPrng::create(&seed).unwrap(); @@ -401,8 +402,8 @@ fn encrypt_decrypt_many_clients_decryptors() -> googletest::Result<()> { let mut expected_output = vec![0; INPUT_LENGTH as usize]; for _ in 0..NUM_CLIENTS { let (kahe_config, ahe_config) = create_shell_configs(&aggregation_config).unwrap(); - let kahe = ShellKahe::new(kahe_config, &public_kahe_seed).unwrap(); - let vahe = ShellVahe::new(ahe_config, &public_ahe_seed).unwrap(); + let kahe = ShellKahe::new(kahe_config, CONTEXT_STRING).unwrap(); + let vahe = ShellVahe::new(ahe_config, CONTEXT_STRING).unwrap(); let common = WillowCommon { kahe, vahe }; let seed = SingleThreadHkdfPrng::generate_seed().unwrap(); let prng = SingleThreadHkdfPrng::create(&seed).unwrap(); @@ -456,12 +457,11 @@ fn encrypt_decrypt_no_dropout() -> googletest::Result<()> { let aggregation_config = generate_aggregation_config(default_id.clone(), 16, 10, NUM_DECRYPTORS, NUM_CLIENTS); let public_kahe_seed = SingleThreadHkdfPrng::generate_seed().unwrap(); - let public_ahe_seed = SingleThreadHkdfPrng::generate_seed().unwrap(); // Create clients. let mut clients = vec![]; for _ in 0..NUM_CLIENTS { - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let seed = SingleThreadHkdfPrng::generate_seed().unwrap(); let prng = SingleThreadHkdfPrng::create(&seed).unwrap(); let client = WillowV1Client { common, prng }; @@ -473,7 +473,7 @@ fn encrypt_decrypt_no_dropout() -> googletest::Result<()> { let mut decryptor_states = vec![]; let mut decryptors = vec![]; for _ in 0..NUM_DECRYPTORS { - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let seed = SingleThreadHkdfPrng::generate_seed().unwrap(); let prng = SingleThreadHkdfPrng::create(&seed).unwrap(); let decryptor_state = DecryptorState::new(); @@ -483,12 +483,12 @@ fn encrypt_decrypt_no_dropout() -> googletest::Result<()> { } // Create server. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let server = WillowV1Server { common }; let mut server_state = ServerState::new(); // Create verifier. - let common = create_willow_common(&aggregation_config, &public_kahe_seed, &public_ahe_seed); + let common = create_willow_common(&aggregation_config, CONTEXT_STRING); let verifier = WillowV1Verifier { common }; let mut verifier_state = VerifierState::new();