From 35160eaa09d3c8b5267866d83c99e19c73e118b0 Mon Sep 17 00:00:00 2001 From: Thomas James Yurek Date: Tue, 10 Dec 2024 00:55:24 -0800 Subject: [PATCH 1/5] wip --- ipa-core/src/cli/crypto/hybrid_decrypt.rs | 10 +- ipa-core/src/query/runner/hybrid.rs | 9 +- ipa-core/src/report/hybrid.rs | 115 ++++++++++++---------- ipa-core/src/report/hybrid_info.rs | 12 ++- ipa-core/src/test_fixture/hybrid.rs | 74 ++++++++++++-- 5 files changed, 146 insertions(+), 74 deletions(-) diff --git a/ipa-core/src/cli/crypto/hybrid_decrypt.rs b/ipa-core/src/cli/crypto/hybrid_decrypt.rs index be705e062..ca233e365 100644 --- a/ipa-core/src/cli/crypto/hybrid_decrypt.rs +++ b/ipa-core/src/cli/crypto/hybrid_decrypt.rs @@ -125,9 +125,8 @@ impl HybridDecryptArgs { ] .reconstruct() .as_u128(); - let key_id = impression_report1.info.key_id; - writeln!(writer, "i,{match_key},{breakdown_key},{key_id}")?; + writeln!(writer, "i,{match_key},{breakdown_key}")?; } ( HybridReport::Conversion(conversion_report1), @@ -149,12 +148,7 @@ impl HybridDecryptArgs { ] .reconstruct() .as_u128(); - let key_id = conversion_report1.info.key_id; - let conversion_site_domain = conversion_report1.info.conversion_site_domain; - let timestamp = conversion_report1.info.timestamp; - let epsilon = conversion_report1.info.epsilon; - let sensitivity = conversion_report1.info.sensitivity; - writeln!(writer, "c,{match_key},{value},{key_id},{conversion_site_domain},{timestamp},{epsilon},{sensitivity}")?; + writeln!(writer, "c,{match_key},{value}")?; } _ => { panic!("Reports are not all the same type"); diff --git a/ipa-core/src/query/runner/hybrid.rs b/ipa-core/src/query/runner/hybrid.rs index 7ed56c69b..5f3b29592 100644 --- a/ipa-core/src/query/runner/hybrid.rs +++ b/ipa-core/src/query/runner/hybrid.rs @@ -242,8 +242,15 @@ mod tests { let shares: [Vec>; 3] = records.iter().cloned().share(); for (buf, shares) in zip(&mut buffers, shares) { for (i, share) in shares.into_iter().enumerate() { + let info = records[i].create_hybrid_info(); share - .delimited_encrypt_to(key_id, key_registry.as_ref(), &mut rng, &mut buf[i % s]) + .delimited_encrypt_to( + key_id, + key_registry.as_ref(), + &info, + &mut rng, + &mut buf[i % s], + ) .unwrap(); } } diff --git a/ipa-core/src/report/hybrid.rs b/ipa-core/src/report/hybrid.rs index bcaca20aa..c04a907e3 100644 --- a/ipa-core/src/report/hybrid.rs +++ b/ipa-core/src/report/hybrid.rs @@ -49,7 +49,7 @@ use crate::{ PublicKeyRegistry, TagSize, }, protocol::ipa_prf::{boolean_ops::expand_shared_array_in_place, shuffle::Shuffleable}, - report::hybrid_info::{HybridConversionInfo, HybridImpressionInfo}, + report::hybrid_info::{HybridConversionInfo, HybridImpressionInfo, HybridInfo}, secret_sharing::{ replicated::{semi_honest::AdditiveShare as Replicated, ReplicatedSecretSharing}, SharedValue, @@ -121,7 +121,6 @@ where { pub match_key: Replicated, pub breakdown_key: Replicated, - pub info: HybridImpressionInfo, } impl HybridImpressionReport @@ -142,7 +141,7 @@ where buf.put_slice(&plaintext_mk); buf.put_slice(&plaintext_bk); - buf.put_slice(&self.info.to_bytes()); + //buf.put_slice(&self.info.to_bytes()); } /// # Errors @@ -155,9 +154,9 @@ where let breakdown_key = Replicated::::deserialize(GenericArray::from_slice(&buf[mk_sz..mk_sz + bk_sz])) .map_err(|e| InvalidHybridReportError::DeserializationError("breakdown_key", e.into()))?; - let info = HybridImpressionInfo::from_bytes(&buf[mk_sz + bk_sz..])?; + //let info = HybridImpressionInfo::from_bytes(&buf[mk_sz + bk_sz..])?; - Ok(Self { match_key, breakdown_key, info }) + Ok(Self { match_key, breakdown_key }) } #[must_use] @@ -185,7 +184,7 @@ where /// # Panics /// If report length does not fit in `u16`. pub fn encrypted_len(&self) -> u16 { - self.ciphertext_len() + u16::try_from(self.info.byte_len()).unwrap() + self.ciphertext_len() //+ u16::try_from(self.info.byte_len()).unwrap() } /// # Errors @@ -194,11 +193,12 @@ where &self, key_id: KeyIdentifier, key_registry: &impl PublicKeyRegistry, + info: &HybridImpressionInfo, rng: &mut R, out: &mut B, ) -> Result<(), InvalidHybridReportError> { - out.put_u16_le(self.encrypted_len()); - self.encrypt_to(key_id, key_registry, rng, out) + out.put_u16_le((self.encrypted_len() + info.byte_len()).try_into().unwrap()); + self.encrypt_to(key_id, key_registry, info, rng, out) } /// # Errors @@ -207,11 +207,12 @@ where &self, key_id: KeyIdentifier, key_registry: &impl PublicKeyRegistry, + info: &HybridImpressionInfo, rng: &mut R, ) -> Result, InvalidHybridReportError> { - let mut out = Vec::with_capacity(usize::from(self.encrypted_len())); - self.encrypt_to(key_id, key_registry, rng, &mut out)?; - debug_assert_eq!(out.len(), usize::from(self.encrypted_len())); + let mut out = Vec::with_capacity(usize::from(self.encrypted_len() + info.byte_len())); + self.encrypt_to(key_id, key_registry, info, rng, &mut out)?; + debug_assert_eq!(out.len(), usize::from(self.encrypted_len() + info.byte_len())); Ok(out) } @@ -221,6 +222,7 @@ where &self, key_id: KeyIdentifier, key_registry: &impl PublicKeyRegistry, + info: &HybridImpressionInfo, rng: &mut R, out: &mut B, ) -> Result<(), InvalidHybridReportError> { @@ -232,8 +234,8 @@ where .serialize(GenericArray::from_mut_slice(&mut plaintext_btt[..])); let pk = key_registry.public_key(key_id).ok_or(CryptError::NoSuchKey(key_id))?; - let info_enc_bytes = self.info.to_enc_bytes(); - let info_bytes = self.info.to_bytes(); + let info_enc_bytes = info.to_enc_bytes(); + let info_bytes = info.to_bytes(); let (encap_key_mk, ciphertext_mk, tag_mk) = seal_in_place( pk, @@ -270,7 +272,6 @@ where { pub match_key: Replicated, pub value: Replicated, - pub info: HybridConversionInfo, } impl HybridConversionReport @@ -291,7 +292,7 @@ where buf.put_slice(&plaintext_mk); buf.put_slice(&plaintext_v); - buf.put_slice(&self.info.to_bytes()); + //buf.put_slice(&self.info.to_bytes()); } /// # Errors @@ -304,8 +305,8 @@ where let value = Replicated::::deserialize(GenericArray::from_slice(&buf[mk_sz..mk_sz + v_sz])) .map_err(|e| InvalidHybridReportError::DeserializationError("breakdown_key", e.into()))?; - let info = HybridConversionInfo::from_bytes(&buf[mk_sz + v_sz..])?; - Ok(Self { match_key, value, info }) + // let info = HybridConversionInfo::from_bytes(&buf[mk_sz + v_sz..])?; + Ok(Self { match_key, value }) } #[must_use] @@ -333,7 +334,7 @@ where /// # Panics /// If report length does not fit in `u16`. pub fn encrypted_len(&self) -> u16 { - self.ciphertext_len() + u16::try_from(self.info.byte_len()).unwrap() + self.ciphertext_len() //+ usize::try_from(self.info.byte_len()).unwrap() } /// # Errors @@ -342,11 +343,12 @@ where &self, key_id: KeyIdentifier, key_registry: &impl PublicKeyRegistry, + info: &HybridConversionInfo, rng: &mut R, out: &mut B, ) -> Result<(), InvalidHybridReportError> { - out.put_u16_le(self.encrypted_len()); - self.encrypt_to(key_id, key_registry, rng, out) + out.put_u16_le(self.encrypted_len() + info.byte_len()); + self.encrypt_to(key_id, key_registry, info, rng, out) } /// # Errors @@ -355,11 +357,12 @@ where &self, key_id: KeyIdentifier, key_registry: &impl PublicKeyRegistry, + info: &HybridConversionInfo, rng: &mut R, ) -> Result, InvalidHybridReportError> { - let mut out = Vec::with_capacity(usize::from(self.encrypted_len())); - self.encrypt_to(key_id, key_registry, rng, &mut out)?; - debug_assert_eq!(out.len(), usize::from(self.encrypted_len())); + let mut out = Vec::with_capacity(usize::from(self.ciphertext_len() + info.byte_len())); + self.encrypt_to(key_id, key_registry, info, rng, &mut out)?; + debug_assert_eq!(out.len(), usize::from(self.encrypted_len() + info.byte_len())); Ok(out) } @@ -369,6 +372,7 @@ where &self, key_id: KeyIdentifier, key_registry: &impl PublicKeyRegistry, + info: &HybridConversionInfo, rng: &mut R, out: &mut B, ) -> Result<(), InvalidHybridReportError> { @@ -381,8 +385,8 @@ where .serialize(GenericArray::from_mut_slice(&mut plaintext_btt[..])); let pk = key_registry.public_key(key_id).ok_or(CryptError::NoSuchKey(key_id))?; - let info_enc_bytes = self.info.to_enc_bytes(); - let info_bytes = self.info.to_bytes(); + let info_enc_bytes = info.to_enc_bytes(); + let info_bytes = info.to_bytes(); let (encap_key_mk, ciphertext_mk, tag_mk) = seal_in_place( pk, @@ -452,19 +456,20 @@ where &self, key_id: KeyIdentifier, key_registry: &impl PublicKeyRegistry, + info: &HybridInfo, rng: &mut R, out: &mut B, ) -> Result<(), InvalidHybridReportError> { match self { HybridReport::Impression(impression_report) => { - out.put_u16_le(self.encrypted_len()); + out.put_u16_le(self.encrypted_len() + info.impression.byte_len()); out.put_u8(HybridEventType::Impression as u8); - impression_report.encrypt_to(key_id, key_registry, rng, out) + impression_report.encrypt_to(key_id, key_registry, &info.impression, rng, out) }, HybridReport::Conversion(conversion_report) => { - out.put_u16_le(self.encrypted_len()); + out.put_u16_le(self.encrypted_len() + info.conversion.byte_len()); out.put_u8(HybridEventType::Conversion as u8); - conversion_report.encrypt_to(key_id, key_registry, rng, out) + conversion_report.encrypt_to(key_id, key_registry, &info.conversion, rng, out) }, } } @@ -475,10 +480,11 @@ where &self, key_id: KeyIdentifier, key_registry: &impl PublicKeyRegistry, + info: &HybridInfo, rng: &mut R, ) -> Result, InvalidHybridReportError> { let mut buf = Vec::new(); - self.encrypt_to(key_id, key_registry, rng, &mut buf)?; + self.encrypt_to(key_id, key_registry, info, rng, &mut buf)?; Ok(buf) } @@ -488,17 +494,18 @@ where &self, key_id: KeyIdentifier, key_registry: &impl PublicKeyRegistry, + info: &HybridInfo, rng: &mut R, out: &mut B, ) -> Result<(), InvalidHybridReportError> { match self { HybridReport::Impression(impression_report) =>{ out.put_u8(HybridEventType::Impression as u8); - impression_report.encrypt_to(key_id, key_registry, rng, out) + impression_report.encrypt_to(key_id, key_registry, &info.impression, rng, out) }, HybridReport::Conversion(conversion_report) => { out.put_u8(HybridEventType::Conversion as u8); - conversion_report.encrypt_to(key_id, key_registry, rng, out) + conversion_report.encrypt_to(key_id, key_registry, &info.conversion, rng, out) }, } } @@ -606,7 +613,7 @@ where .map_err(|e| { InvalidHybridReportError::DeserializationError("is_trigger", e.into()) })?, - info, + //info, }) } } @@ -709,7 +716,7 @@ where value: Replicated::::deserialize(GenericArray::from_slice(plaintext_btt)).map_err( |e| InvalidHybridReportError::DeserializationError("trigger_value", e.into()), )?, - info, + //info, }) } } @@ -1249,7 +1256,7 @@ mod test { hpke::{KeyPair, KeyRegistry}, report::{ hybrid::{EncryptedHybridConversionReport, HybridEventType}, - hybrid_info::{HybridConversionInfo, HybridImpressionInfo}, + hybrid_info::{HybridConversionInfo, HybridImpressionInfo, HybridInfo}, }, secret_sharing::replicated::{ semi_honest::{AdditiveShare as Replicated, AdditiveShare}, @@ -1267,21 +1274,21 @@ mod test { HybridReport::Impression(HybridImpressionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), breakdown_key: AdditiveShare::new(rng.gen(), rng.gen()), - info: HybridImpressionInfo::new(0), + //info: HybridImpressionInfo::new(0), }) } HybridEventType::Conversion => { HybridReport::Conversion(HybridConversionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), value: AdditiveShare::new(rng.gen(), rng.gen()), - info: HybridConversionInfo::new( + /*info: HybridConversionInfo::new( 0, "https://www.example2.com", rng.gen(), 0.0, 0.0, ) - .unwrap(), + .unwrap(),*/ }) } } @@ -1308,8 +1315,8 @@ mod test { let conversion_report = HybridConversionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), value: AdditiveShare::new(rng.gen(), rng.gen()), - info: HybridConversionInfo::new(0, "https://www.example2.com", 1_234_567, 0.0, 0.0) - .unwrap(), + //info: HybridConversionInfo::new(0, "https://www.example2.com", 1_234_567, 0.0, 0.0) + // .unwrap(), }; let indistinguishable_report: IndistinguishableHybridReport = conversion_report.clone().into(); @@ -1339,7 +1346,7 @@ mod test { let impression_report = HybridImpressionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), breakdown_key: AdditiveShare::new(rng.gen(), rng.gen()), - info: HybridImpressionInfo::new(0), + //info: HybridImpressionInfo::new(0), }; let indistinguishable_report: IndistinguishableHybridReport = impression_report.clone().into(); @@ -1389,7 +1396,7 @@ mod test { let hybrid_impression_report = HybridImpressionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), breakdown_key: AdditiveShare::new(rng.gen(), rng.gen()), - info: HybridImpressionInfo::new(0), + //info: HybridImpressionInfo::new(0), }; let mut hybrid_impression_report_bytes = Vec::with_capacity(HybridImpressionReport::::serialized_len()); @@ -1408,8 +1415,8 @@ mod test { let hybrid_conversion_report = HybridConversionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), value: AdditiveShare::new(rng.gen(), rng.gen()), - info: HybridConversionInfo::new(0, "https://www.example2.com", 1_234_567, 0.0, 0.0) - .unwrap(), + //info: HybridConversionInfo::new(0, "https://www.example2.com", 1_234_567, 0.0, 0.0) + // .unwrap(), }; let mut hybrid_conversion_report_bytes = Vec::with_capacity(HybridImpressionReport::::serialized_len()); @@ -1431,11 +1438,12 @@ mod test { let hybrid_impression_report = HybridImpressionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), breakdown_key: AdditiveShare::new(rng.gen(), rng.gen()), - info: HybridImpressionInfo::new(key_id), + //info: HybridImpressionInfo::new(key_id), }; + let impression_info = HybridImpressionInfo::new(key_id); let enc_report_bytes = hybrid_impression_report - .encrypt(key_id, &key_registry, &mut rng) + .encrypt(key_id, &key_registry, &impression_info, &mut rng) .unwrap(); let enc_report = @@ -1454,14 +1462,16 @@ mod test { let hybrid_conversion_report = HybridConversionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), value: AdditiveShare::new(rng.gen(), rng.gen()), - info: HybridConversionInfo::new(0, "meta.com", 1_729_707_432, 5.0, 1.1).unwrap(), + //info: HybridConversionInfo::new(0, "meta.com", 1_729_707_432, 5.0, 1.1).unwrap(), }; let key_registry = KeyRegistry::::random(1, &mut rng); let key_id = 0; + let conversion_info = + HybridConversionInfo::new(0, "meta.com", 1_729_707_432, 5.0, 1.1).unwrap(); let enc_report_bytes = hybrid_conversion_report - .encrypt(key_id, &key_registry, &mut rng) + .encrypt(key_id, &key_registry, &conversion_info, &mut rng) .unwrap(); let enc_report = @@ -1482,9 +1492,10 @@ mod test { let key_registry = KeyRegistry::::random(1, &mut rng); let key_id = 0; + let info = HybridInfo::new(0, "meta.com", 1_729_707_432, 5.0, 1.1).unwrap(); let enc_report_bytes = hybrid_report - .encrypt(key_id, &key_registry, &mut rng) + .encrypt(key_id, &key_registry, &info, &mut rng) .unwrap(); let enc_report = @@ -1501,14 +1512,16 @@ mod test { let hybrid_conversion_report = HybridConversionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), value: AdditiveShare::new(rng.gen(), rng.gen()), - info: HybridConversionInfo::new(0, "meta.com", 1_729_707_432, 5.0, 1.1).unwrap(), + //info: HybridConversionInfo::new(0, "meta.com", 1_729_707_432, 5.0, 1.1).unwrap(), }; let key_registry = KeyRegistry::::random(1, &mut rng); let key_id = 0; + let conversion_info = + HybridConversionInfo::new(0, "meta.com", 1_729_707_432, 5.0, 1.1).unwrap(); let enc_report_bytes = hybrid_conversion_report - .encrypt(key_id, &key_registry, &mut rng) + .encrypt(key_id, &key_registry, &conversion_info, &mut rng) .unwrap(); let mut enc_report_bytes2 = enc_report_bytes.clone(); diff --git a/ipa-core/src/report/hybrid_info.rs b/ipa-core/src/report/hybrid_info.rs index 31da9f68e..b07cbbedb 100644 --- a/ipa-core/src/report/hybrid_info.rs +++ b/ipa-core/src/report/hybrid_info.rs @@ -18,10 +18,12 @@ impl HybridImpressionInfo { } #[must_use] - pub fn byte_len(&self) -> usize { + /// # Panics + /// If report length does not fit in `u16`. + pub fn byte_len(&self) -> u16 { let out_len = std::mem::size_of_val(&self.key_id); debug_assert_eq!(out_len, self.to_bytes().len(), "Serialization length estimation is incorrect and leads to extra allocation or wasted memory"); - out_len + out_len.try_into().unwrap() } // Converts this instance into an owned byte slice. DO NOT USE AS INPUT TO HPKE @@ -99,7 +101,9 @@ impl HybridConversionInfo { } #[must_use] - pub fn byte_len(&self) -> usize { + /// # Panics + /// If report length does not fit in `u16`. + pub fn byte_len(&self) -> u16 { let out_len = std::mem::size_of_val(&self.key_id) + 1 // delimiter + self.conversion_site_domain.len() @@ -107,7 +111,7 @@ impl HybridConversionInfo { + std::mem::size_of_val(&self.epsilon) + std::mem::size_of_val(&self.sensitivity); debug_assert_eq!(out_len, self.to_bytes().len(), "Serialization length estimation is incorrect and leads to extra allocation or wasted memory"); - out_len + out_len.try_into().unwrap() } // Converts this instance into an owned byte slice. DO NOT USE AS INPUT TO HPKE diff --git a/ipa-core/src/test_fixture/hybrid.rs b/ipa-core/src/test_fixture/hybrid.rs index ba1b19e2c..a3544632e 100644 --- a/ipa-core/src/test_fixture/hybrid.rs +++ b/ipa-core/src/test_fixture/hybrid.rs @@ -11,7 +11,7 @@ use crate::{ AggregateableHybridReport, HybridConversionReport, HybridImpressionReport, HybridReport, IndistinguishableHybridReport, KeyIdentifier, }, - hybrid_info::{HybridConversionInfo, HybridImpressionInfo}, + hybrid_info::{HybridConversionInfo, HybridImpressionInfo, HybridInfo}, }, secret_sharing::{replicated::semi_honest::AdditiveShare as Replicated, IntoShares}, test_fixture::sharing::Reconstruct, @@ -133,7 +133,7 @@ where TestHybridRecord::TestImpression { match_key, breakdown_key, - key_id, + key_id: _, } => { let ba_match_key = BA64::try_from(u128::from(match_key)) .unwrap() @@ -146,7 +146,7 @@ where HybridReport::Impression::(HybridImpressionReport { match_key: match_key_share, breakdown_key: breakdown_key_share, - info: HybridImpressionInfo::new(key_id), + //info: HybridImpressionInfo::new(key_id), }) }) .collect::>() @@ -156,11 +156,11 @@ where TestHybridRecord::TestConversion { match_key, value, - key_id, - conversion_site_domain, - timestamp, - epsilon, - sensitivity, + key_id: _, + conversion_site_domain: _, + timestamp: _, + epsilon: _, + sensitivity: _, } => { let ba_match_key = BA64::try_from(u128::from(match_key)) .unwrap() @@ -171,14 +171,14 @@ where HybridReport::Conversion::(HybridConversionReport { match_key: match_key_share, value: value_share, - info: HybridConversionInfo::new( + /*info: HybridConversionInfo::new( key_id, &conversion_site_domain, timestamp, epsilon, sensitivity, ) - .unwrap(), + .unwrap(),*/ }) }) .collect::>() @@ -189,6 +189,60 @@ where } } +impl TestHybridRecord { + pub fn create_hybrid_info(&self) -> HybridInfo { + match self { + TestHybridRecord::TestImpression { + match_key: _, + breakdown_key: _, + key_id, + } => { + let conversion = HybridConversionInfo { + key_id: key_id.clone(), + conversion_site_domain: "".to_string(), + timestamp: 0, + epsilon: 0.0, + sensitivity: 0.0, + }; + let impression = HybridImpressionInfo { + key_id: key_id.clone(), + }; + HybridInfo { + impression, + conversion, + } + } + TestHybridRecord::TestConversion { + match_key: _, + value: _, + key_id, + conversion_site_domain, + timestamp, + epsilon, + sensitivity, + } => { + let key_id = key_id.clone(); + let conversion_site_domain = conversion_site_domain.clone(); + let timestamp = timestamp.clone(); + let epsilon = epsilon.clone(); + let sensitivity = sensitivity.clone(); + let impression = HybridImpressionInfo { key_id }; + let conversion = HybridConversionInfo { + key_id, + conversion_site_domain, + timestamp, + epsilon, + sensitivity, + }; + HybridInfo { + impression, + conversion, + } + } + } + } +} + enum MatchEntry { Single(TestHybridRecord), Pair(TestHybridRecord, TestHybridRecord), From e3daf23f939994f2747842c55a08b6a15d21104a Mon Sep 17 00:00:00 2001 From: Thomas James Yurek Date: Tue, 10 Dec 2024 16:33:37 -0800 Subject: [PATCH 2/5] stuff works O.o --- ipa-core/src/cli/crypto/hybrid_decrypt.rs | 28 ++++-- ipa-core/src/cli/crypto/hybrid_encrypt.rs | 23 +++-- ipa-core/src/report/hybrid.rs | 105 +++++++++++++++++----- ipa-core/src/report/hybrid_info.rs | 28 ++++++ ipa-core/src/test_fixture/hybrid.rs | 19 ++-- 5 files changed, 157 insertions(+), 46 deletions(-) diff --git a/ipa-core/src/cli/crypto/hybrid_decrypt.rs b/ipa-core/src/cli/crypto/hybrid_decrypt.rs index ca233e365..db4b33877 100644 --- a/ipa-core/src/cli/crypto/hybrid_decrypt.rs +++ b/ipa-core/src/cli/crypto/hybrid_decrypt.rs @@ -14,7 +14,10 @@ use crate::{ U128Conversions, }, hpke::{KeyRegistry, PrivateKeyOnly}, - report::hybrid::{EncryptedHybridReport, HybridReport}, + report::{ + hybrid::{EncryptedHybridReport, HybridReport}, + hybrid_info::HybridInfo, + }, test_fixture::Reconstruct, }; @@ -104,7 +107,7 @@ impl HybridDecryptArgs { for (dec_report1, (dec_report2, dec_report3)) in decrypted_reports1.zip(decrypted_reports2.zip(decrypted_reports3)) { - match (dec_report1, dec_report2, dec_report3) { + match (dec_report1.0, dec_report2.0, dec_report3.0) { ( HybridReport::Impression(impression_report1), HybridReport::Impression(impression_report2), @@ -125,8 +128,9 @@ impl HybridDecryptArgs { ] .reconstruct() .as_u128(); + let key_id = dec_report1.1.impression.key_id; - writeln!(writer, "i,{match_key},{breakdown_key}")?; + writeln!(writer, "i,{match_key},{breakdown_key},{key_id}")?; } ( HybridReport::Conversion(conversion_report1), @@ -148,7 +152,14 @@ impl HybridDecryptArgs { ] .reconstruct() .as_u128(); - writeln!(writer, "c,{match_key},{value}")?; + + let key_id = dec_report1.1.conversion.key_id; + let conversion_site_domain = dec_report1.1.conversion.conversion_site_domain; + let timestamp = dec_report1.1.conversion.timestamp; + let epsilon = dec_report1.1.conversion.epsilon; + let sensitivity = dec_report1.1.conversion.sensitivity; + + writeln!(writer, "c,{match_key},{value},{key_id},{conversion_site_domain},{timestamp},{epsilon},{sensitivity}")?; } _ => { panic!("Reports are not all the same type"); @@ -166,7 +177,7 @@ struct DecryptedHybridReports { } impl Iterator for DecryptedHybridReports { - type Item = HybridReport; + type Item = (HybridReport, HybridInfo); fn next(&mut self) -> Option { let mut line = String::new(); @@ -174,9 +185,10 @@ impl Iterator for DecryptedHybridReports { let encrypted_report_bytes = hex::decode(line.trim()).unwrap(); let enc_report = EncryptedHybridReport::from_bytes(encrypted_report_bytes.into()).unwrap(); - let dec_report: HybridReport = - enc_report.decrypt(&self.key_registry).unwrap(); - Some(dec_report) + let (dec_report, info) = enc_report + .decrypt_and_return_info(&self.key_registry) + .unwrap(); + Some((dec_report, info)) } else { None } diff --git a/ipa-core/src/cli/crypto/hybrid_encrypt.rs b/ipa-core/src/cli/crypto/hybrid_encrypt.rs index 1a60d6944..b37907b78 100644 --- a/ipa-core/src/cli/crypto/hybrid_encrypt.rs +++ b/ipa-core/src/cli/crypto/hybrid_encrypt.rs @@ -21,14 +21,22 @@ use crate::{ config::{KeyRegistries, NetworkConfig}, error::BoxError, hpke::{KeyRegistry, PublicKeyOnly}, - report::hybrid::{HybridReport, DEFAULT_KEY_ID}, + report::{ + hybrid::{HybridReport, DEFAULT_KEY_ID}, + hybrid_info::HybridInfo, + }, secret_sharing::IntoShares, test_fixture::hybrid::TestHybridRecord, }; /// Encryptor takes 3 arguments: `report_id`, helper that the shares must be encrypted towards /// and the actual share ([`HybridReport`]) to encrypt. -type EncryptorInput = (usize, usize, HybridReport); +type EncryptorInput = ( + usize, + usize, + HybridReport, + HybridInfo, +); /// Encryptor sends report id and encrypted bytes down to file worker to write those bytes /// down type EncryptorOutput = (usize, Vec); @@ -91,7 +99,8 @@ impl HybridEncryptArgs { let mut worker_pool = ReportWriter::new(key_registries, &self.output_dir); for (report_id, record) in input.iter::().enumerate() { - worker_pool.submit(report_id, record.share())?; + let info = record.create_hybrid_info(); + worker_pool.submit(report_id, record.share(), &info)?; } worker_pool.join()?; @@ -130,11 +139,12 @@ impl EncryptorPool { std::thread::Builder::new() .name(format!("encryptor-{i}")) .spawn(move || { - for (i, helper_id, report) in rx { + for (i, helper_id, report, info) in rx { let key_registry = &key_registries[helper_id]; let output = report.encrypt( DEFAULT_KEY_ID, key_registry, + &info, &mut thread_rng(), )?; file_writer[helper_id].send((i, output))?; @@ -206,9 +216,12 @@ impl ReportWriter { &mut self, report_id: usize, shares: [HybridReport; 3], + info: &HybridInfo, ) -> UnitResult { for (i, share) in shares.into_iter().enumerate() { - self.encryptor_pool.encrypt_share((report_id, i, share))?; + // todo: maybe a smart pointer to avoid cloning + self.encryptor_pool + .encrypt_share((report_id, i, share, info.clone()))?; } Ok(()) diff --git a/ipa-core/src/report/hybrid.rs b/ipa-core/src/report/hybrid.rs index c04a907e3..085622d64 100644 --- a/ipa-core/src/report/hybrid.rs +++ b/ipa-core/src/report/hybrid.rs @@ -197,7 +197,7 @@ where rng: &mut R, out: &mut B, ) -> Result<(), InvalidHybridReportError> { - out.put_u16_le((self.encrypted_len() + info.byte_len()).try_into().unwrap()); + out.put_u16_le(self.encrypted_len() + info.byte_len()); self.encrypt_to(key_id, key_registry, info, rng, out) } @@ -581,10 +581,10 @@ where /// ## Panics /// Should not panic. Only panics if a `Report` constructor failed to validate the /// contents properly, which would be a bug. - pub fn decrypt( + pub fn decrypt_and_return_info( &self, key_registry: &P, - ) -> Result, InvalidHybridReportError> { + ) -> Result<(HybridImpressionReport, HybridImpressionInfo), InvalidHybridReportError> { type CTMKLength = Sum< as Serializable>::Size, TagSize>; type CTBTTLength = < as Serializable>::Size as Add>::Output; @@ -605,16 +605,35 @@ where let plaintext_btt = open_in_place(sk, self.encap_key_btt(), &mut ct_btt, &info_enc_bytes)?; - Ok(HybridImpressionReport:: { - match_key: Replicated::::deserialize_infallible(GenericArray::from_slice( - plaintext_mk, - )), - breakdown_key: Replicated::::deserialize(GenericArray::from_slice(plaintext_btt)) + Ok(( + HybridImpressionReport:: { + match_key: Replicated::::deserialize_infallible(GenericArray::from_slice( + plaintext_mk, + )), + breakdown_key: Replicated::::deserialize(GenericArray::from_slice( + plaintext_btt, + )) .map_err(|e| { - InvalidHybridReportError::DeserializationError("is_trigger", e.into()) - })?, - //info, - }) + InvalidHybridReportError::DeserializationError("is_trigger", e.into()) + })?, + //info, + }, + info, + )) + } + + /// ## Errors + /// If the match key shares in the report cannot be decrypted (e.g. due to a + /// failure of the authenticated encryption). + /// ## Panics + /// Should not panic. Only panics if a `Report` constructor failed to validate the + /// contents properly, which would be a bug. + pub fn decrypt( + &self, + key_registry: &P, + ) -> Result, InvalidHybridReportError> { + let (report, _) = self.decrypt_and_return_info(key_registry)?; + Ok(report) } } @@ -686,10 +705,10 @@ where /// ## Panics /// Should not panic. Only panics if a `Report` constructor failed to validate the /// contents properly, which would be a bug. - pub fn decrypt( + pub fn decrypt_and_return_info( &self, key_registry: &P, - ) -> Result, InvalidHybridReportError> { + ) -> Result<(HybridConversionReport, HybridConversionInfo), InvalidHybridReportError> { type CTMKLength = Sum< as Serializable>::Size, TagSize>; type CTBTTLength = < as Serializable>::Size as Add>::Output; @@ -709,15 +728,33 @@ where GenericArray::from_slice(self.btt_ciphertext()).clone(); let plaintext_btt = open_in_place(sk, self.encap_key_btt(), &mut ct_btt, &info_enc_bytes)?; - Ok(HybridConversionReport:: { - match_key: Replicated::::deserialize_infallible(GenericArray::from_slice( - plaintext_mk, - )), - value: Replicated::::deserialize(GenericArray::from_slice(plaintext_btt)).map_err( - |e| InvalidHybridReportError::DeserializationError("trigger_value", e.into()), - )?, - //info, - }) + Ok(( + HybridConversionReport:: { + match_key: Replicated::::deserialize_infallible(GenericArray::from_slice( + plaintext_mk, + )), + value: Replicated::::deserialize(GenericArray::from_slice(plaintext_btt)) + .map_err(|e| { + InvalidHybridReportError::DeserializationError("trigger_value", e.into()) + })?, + //info, + }, + info, + )) + } + + /// ## Errors + /// If the match key shares in the report cannot be decrypted (e.g. due to a + /// failure of the authenticated encryption). + /// ## Panics + /// Should not panic. Only panics if a `Report` constructor failed to validate the + /// contents properly, which would be a bug. + pub fn decrypt( + &self, + key_registry: &P, + ) -> Result, InvalidHybridReportError> { + let (report, _) = self.decrypt_and_return_info(key_registry)?; + Ok(report) } } @@ -1083,6 +1120,28 @@ where } } } + /// ## Errors + /// If the match key shares in the report cannot be decrypted (e.g. due to a + /// failure of the authenticated encryption). + /// ## Panics + /// Should not panic. Only panics if a `Report` constructor failed to validate the + /// contents properly, which would be a bug. + pub fn decrypt_and_return_info( + &self, + key_registry: &P, + ) -> Result<(HybridReport, HybridInfo), InvalidHybridReportError> { + match self { + EncryptedHybridReport::Impression(impression_report) => { + let (report, info) = impression_report.decrypt_and_return_info(key_registry)?; + Ok((HybridReport::Impression(report), info.into())) + } + EncryptedHybridReport::Conversion(conversion_report) => { + let (report, info) = conversion_report.decrypt_and_return_info(key_registry)?; + Ok((HybridReport::Conversion(report), info.into())) + } + } + } + /// ## Errors /// If the match key shares in the report cannot be decrypted (e.g. due to a /// failure of the authenticated encryption). diff --git a/ipa-core/src/report/hybrid_info.rs b/ipa-core/src/report/hybrid_info.rs index b07cbbedb..51ffb71f5 100644 --- a/ipa-core/src/report/hybrid_info.rs +++ b/ipa-core/src/report/hybrid_info.rs @@ -254,6 +254,34 @@ impl HybridInfo { } } +impl From for HybridInfo { + fn from(impression: HybridImpressionInfo) -> Self { + let conversion = HybridConversionInfo { + key_id: impression.key_id, + conversion_site_domain: String::new(), + timestamp: 0, + epsilon: 0.0, + sensitivity: 0.0, + }; + Self { + impression, + conversion, + } + } +} + +impl From for HybridInfo { + fn from(conversion: HybridConversionInfo) -> Self { + let impression = HybridImpressionInfo { + key_id: conversion.key_id, + }; + Self { + impression, + conversion, + } + } +} + #[cfg(all(test, unit_test))] mod test { use super::*; diff --git a/ipa-core/src/test_fixture/hybrid.rs b/ipa-core/src/test_fixture/hybrid.rs index a3544632e..2868524a2 100644 --- a/ipa-core/src/test_fixture/hybrid.rs +++ b/ipa-core/src/test_fixture/hybrid.rs @@ -190,6 +190,7 @@ where } impl TestHybridRecord { + #[must_use] pub fn create_hybrid_info(&self) -> HybridInfo { match self { TestHybridRecord::TestImpression { @@ -198,15 +199,13 @@ impl TestHybridRecord { key_id, } => { let conversion = HybridConversionInfo { - key_id: key_id.clone(), - conversion_site_domain: "".to_string(), + key_id: *key_id, + conversion_site_domain: String::new(), timestamp: 0, epsilon: 0.0, sensitivity: 0.0, }; - let impression = HybridImpressionInfo { - key_id: key_id.clone(), - }; + let impression = HybridImpressionInfo { key_id: *key_id }; HybridInfo { impression, conversion, @@ -221,11 +220,11 @@ impl TestHybridRecord { epsilon, sensitivity, } => { - let key_id = key_id.clone(); - let conversion_site_domain = conversion_site_domain.clone(); - let timestamp = timestamp.clone(); - let epsilon = epsilon.clone(); - let sensitivity = sensitivity.clone(); + let key_id = *key_id; + let conversion_site_domain = conversion_site_domain.to_string(); + let timestamp = *timestamp; + let epsilon = *epsilon; + let sensitivity = *sensitivity; let impression = HybridImpressionInfo { key_id }; let conversion = HybridConversionInfo { key_id, From 9f62a4ad0250895fc8b62f30ac4f9834db5b1db3 Mon Sep 17 00:00:00 2001 From: Thomas James Yurek Date: Tue, 10 Dec 2024 16:42:21 -0800 Subject: [PATCH 3/5] cleanup comments --- ipa-core/src/cli/crypto/hybrid_encrypt.rs | 4 ++-- ipa-core/src/report/hybrid.rs | 25 +---------------------- 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/ipa-core/src/cli/crypto/hybrid_encrypt.rs b/ipa-core/src/cli/crypto/hybrid_encrypt.rs index b37907b78..658d5d8b0 100644 --- a/ipa-core/src/cli/crypto/hybrid_encrypt.rs +++ b/ipa-core/src/cli/crypto/hybrid_encrypt.rs @@ -29,8 +29,8 @@ use crate::{ test_fixture::hybrid::TestHybridRecord, }; -/// Encryptor takes 3 arguments: `report_id`, helper that the shares must be encrypted towards -/// and the actual share ([`HybridReport`]) to encrypt. +/// Encryptor takes 4 arguments: `report_id`, helper that the shares must be encrypted towards, +/// AAD info, and the actual share ([`HybridReport`]) to encrypt. type EncryptorInput = ( usize, usize, diff --git a/ipa-core/src/report/hybrid.rs b/ipa-core/src/report/hybrid.rs index 085622d64..0ccf815ff 100644 --- a/ipa-core/src/report/hybrid.rs +++ b/ipa-core/src/report/hybrid.rs @@ -141,7 +141,6 @@ where buf.put_slice(&plaintext_mk); buf.put_slice(&plaintext_bk); - //buf.put_slice(&self.info.to_bytes()); } /// # Errors @@ -292,7 +291,6 @@ where buf.put_slice(&plaintext_mk); buf.put_slice(&plaintext_v); - //buf.put_slice(&self.info.to_bytes()); } /// # Errors @@ -305,7 +303,6 @@ where let value = Replicated::::deserialize(GenericArray::from_slice(&buf[mk_sz..mk_sz + v_sz])) .map_err(|e| InvalidHybridReportError::DeserializationError("breakdown_key", e.into()))?; - // let info = HybridConversionInfo::from_bytes(&buf[mk_sz + v_sz..])?; Ok(Self { match_key, value }) } @@ -334,7 +331,7 @@ where /// # Panics /// If report length does not fit in `u16`. pub fn encrypted_len(&self) -> u16 { - self.ciphertext_len() //+ usize::try_from(self.info.byte_len()).unwrap() + self.ciphertext_len() } /// # Errors @@ -616,7 +613,6 @@ where .map_err(|e| { InvalidHybridReportError::DeserializationError("is_trigger", e.into()) })?, - //info, }, info, )) @@ -737,7 +733,6 @@ where .map_err(|e| { InvalidHybridReportError::DeserializationError("trigger_value", e.into()) })?, - //info, }, info, )) @@ -1333,21 +1328,12 @@ mod test { HybridReport::Impression(HybridImpressionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), breakdown_key: AdditiveShare::new(rng.gen(), rng.gen()), - //info: HybridImpressionInfo::new(0), }) } HybridEventType::Conversion => { HybridReport::Conversion(HybridConversionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), value: AdditiveShare::new(rng.gen(), rng.gen()), - /*info: HybridConversionInfo::new( - 0, - "https://www.example2.com", - rng.gen(), - 0.0, - 0.0, - ) - .unwrap(),*/ }) } } @@ -1374,8 +1360,6 @@ mod test { let conversion_report = HybridConversionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), value: AdditiveShare::new(rng.gen(), rng.gen()), - //info: HybridConversionInfo::new(0, "https://www.example2.com", 1_234_567, 0.0, 0.0) - // .unwrap(), }; let indistinguishable_report: IndistinguishableHybridReport = conversion_report.clone().into(); @@ -1405,7 +1389,6 @@ mod test { let impression_report = HybridImpressionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), breakdown_key: AdditiveShare::new(rng.gen(), rng.gen()), - //info: HybridImpressionInfo::new(0), }; let indistinguishable_report: IndistinguishableHybridReport = impression_report.clone().into(); @@ -1455,7 +1438,6 @@ mod test { let hybrid_impression_report = HybridImpressionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), breakdown_key: AdditiveShare::new(rng.gen(), rng.gen()), - //info: HybridImpressionInfo::new(0), }; let mut hybrid_impression_report_bytes = Vec::with_capacity(HybridImpressionReport::::serialized_len()); @@ -1474,8 +1456,6 @@ mod test { let hybrid_conversion_report = HybridConversionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), value: AdditiveShare::new(rng.gen(), rng.gen()), - //info: HybridConversionInfo::new(0, "https://www.example2.com", 1_234_567, 0.0, 0.0) - // .unwrap(), }; let mut hybrid_conversion_report_bytes = Vec::with_capacity(HybridImpressionReport::::serialized_len()); @@ -1497,7 +1477,6 @@ mod test { let hybrid_impression_report = HybridImpressionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), breakdown_key: AdditiveShare::new(rng.gen(), rng.gen()), - //info: HybridImpressionInfo::new(key_id), }; let impression_info = HybridImpressionInfo::new(key_id); @@ -1521,7 +1500,6 @@ mod test { let hybrid_conversion_report = HybridConversionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), value: AdditiveShare::new(rng.gen(), rng.gen()), - //info: HybridConversionInfo::new(0, "meta.com", 1_729_707_432, 5.0, 1.1).unwrap(), }; let key_registry = KeyRegistry::::random(1, &mut rng); @@ -1571,7 +1549,6 @@ mod test { let hybrid_conversion_report = HybridConversionReport:: { match_key: AdditiveShare::new(rng.gen(), rng.gen()), value: AdditiveShare::new(rng.gen(), rng.gen()), - //info: HybridConversionInfo::new(0, "meta.com", 1_729_707_432, 5.0, 1.1).unwrap(), }; let key_registry = KeyRegistry::::random(1, &mut rng); From e69a1eef3bebd933587486dad8c40283a447dd73 Mon Sep 17 00:00:00 2001 From: Thomas James Yurek Date: Tue, 10 Dec 2024 16:46:20 -0800 Subject: [PATCH 4/5] last bit --- ipa-core/src/report/hybrid.rs | 3 +-- ipa-core/src/test_fixture/hybrid.rs | 8 -------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/ipa-core/src/report/hybrid.rs b/ipa-core/src/report/hybrid.rs index 0ccf815ff..c8cccd184 100644 --- a/ipa-core/src/report/hybrid.rs +++ b/ipa-core/src/report/hybrid.rs @@ -153,7 +153,6 @@ where let breakdown_key = Replicated::::deserialize(GenericArray::from_slice(&buf[mk_sz..mk_sz + bk_sz])) .map_err(|e| InvalidHybridReportError::DeserializationError("breakdown_key", e.into()))?; - //let info = HybridImpressionInfo::from_bytes(&buf[mk_sz + bk_sz..])?; Ok(Self { match_key, breakdown_key }) } @@ -183,7 +182,7 @@ where /// # Panics /// If report length does not fit in `u16`. pub fn encrypted_len(&self) -> u16 { - self.ciphertext_len() //+ u16::try_from(self.info.byte_len()).unwrap() + self.ciphertext_len() } /// # Errors diff --git a/ipa-core/src/test_fixture/hybrid.rs b/ipa-core/src/test_fixture/hybrid.rs index 2868524a2..466fa4a4c 100644 --- a/ipa-core/src/test_fixture/hybrid.rs +++ b/ipa-core/src/test_fixture/hybrid.rs @@ -171,14 +171,6 @@ where HybridReport::Conversion::(HybridConversionReport { match_key: match_key_share, value: value_share, - /*info: HybridConversionInfo::new( - key_id, - &conversion_site_domain, - timestamp, - epsilon, - sensitivity, - ) - .unwrap(),*/ }) }) .collect::>() From 2df795f4b69c1ba6913a96ee49e2c0142ce7750b Mon Sep 17 00:00:00 2001 From: Thomas James Yurek Date: Thu, 12 Dec 2024 10:03:18 -0800 Subject: [PATCH 5/5] shuffle around u16/usize length handling stuff --- ipa-core/src/report/hybrid.rs | 26 ++++++++++++++++++-------- ipa-core/src/report/hybrid_info.rs | 10 ++++------ 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/ipa-core/src/report/hybrid.rs b/ipa-core/src/report/hybrid.rs index c8cccd184..576c36a60 100644 --- a/ipa-core/src/report/hybrid.rs +++ b/ipa-core/src/report/hybrid.rs @@ -187,6 +187,8 @@ where /// # Errors /// If there is a problem encrypting the report. + /// # Panics + /// If info length + report length does not fit in `u16`. pub fn delimited_encrypt_to( &self, key_id: KeyIdentifier, @@ -195,12 +197,14 @@ where rng: &mut R, out: &mut B, ) -> Result<(), InvalidHybridReportError> { - out.put_u16_le(self.encrypted_len() + info.byte_len()); + out.put_u16_le(self.encrypted_len() + u16::try_from(info.byte_len()).unwrap()); self.encrypt_to(key_id, key_registry, info, rng, out) } /// # Errors /// If there is a problem encrypting the report. + /// # Panics + /// If info length + report length does not fit in `u16`. pub fn encrypt( &self, key_id: KeyIdentifier, @@ -208,9 +212,9 @@ where info: &HybridImpressionInfo, rng: &mut R, ) -> Result, InvalidHybridReportError> { - let mut out = Vec::with_capacity(usize::from(self.encrypted_len() + info.byte_len())); + let mut out = Vec::with_capacity(usize::from(self.encrypted_len() + u16::try_from(info.byte_len()).unwrap())); self.encrypt_to(key_id, key_registry, info, rng, &mut out)?; - debug_assert_eq!(out.len(), usize::from(self.encrypted_len() + info.byte_len())); + debug_assert_eq!(out.len(), usize::from(self.encrypted_len() + u16::try_from(info.byte_len()).unwrap())); Ok(out) } @@ -335,6 +339,8 @@ where /// # Errors /// If there is a problem encrypting the report. + /// # Panics + /// If info length + report length does not fit in `u16`. pub fn delimited_encrypt_to( &self, key_id: KeyIdentifier, @@ -343,12 +349,14 @@ where rng: &mut R, out: &mut B, ) -> Result<(), InvalidHybridReportError> { - out.put_u16_le(self.encrypted_len() + info.byte_len()); + out.put_u16_le(self.encrypted_len() + u16::try_from(info.byte_len()).unwrap()); self.encrypt_to(key_id, key_registry, info, rng, out) } /// # Errors /// If there is a problem encrypting the report. + /// # Panics + /// If info length + report length does not fit in `u16`. pub fn encrypt( &self, key_id: KeyIdentifier, @@ -356,9 +364,9 @@ where info: &HybridConversionInfo, rng: &mut R, ) -> Result, InvalidHybridReportError> { - let mut out = Vec::with_capacity(usize::from(self.ciphertext_len() + info.byte_len())); + let mut out = Vec::with_capacity(usize::from(self.ciphertext_len() + u16::try_from(info.byte_len()).unwrap())); self.encrypt_to(key_id, key_registry, info, rng, &mut out)?; - debug_assert_eq!(out.len(), usize::from(self.encrypted_len() + info.byte_len())); + debug_assert_eq!(out.len(), usize::from(self.encrypted_len() + u16::try_from(info.byte_len()).unwrap())); Ok(out) } @@ -448,6 +456,8 @@ where /// # Errors /// If there is a problem encrypting the report. + /// # Panics + /// If info length + report length does not fit in `u16`. pub fn delimited_encrypt_to( &self, key_id: KeyIdentifier, @@ -458,12 +468,12 @@ where ) -> Result<(), InvalidHybridReportError> { match self { HybridReport::Impression(impression_report) => { - out.put_u16_le(self.encrypted_len() + info.impression.byte_len()); + out.put_u16_le(self.encrypted_len() + u16::try_from(info.impression.byte_len()).unwrap()); out.put_u8(HybridEventType::Impression as u8); impression_report.encrypt_to(key_id, key_registry, &info.impression, rng, out) }, HybridReport::Conversion(conversion_report) => { - out.put_u16_le(self.encrypted_len() + info.conversion.byte_len()); + out.put_u16_le(self.encrypted_len() + u16::try_from(info.conversion.byte_len()).unwrap()); out.put_u8(HybridEventType::Conversion as u8); conversion_report.encrypt_to(key_id, key_registry, &info.conversion, rng, out) }, diff --git a/ipa-core/src/report/hybrid_info.rs b/ipa-core/src/report/hybrid_info.rs index 51ffb71f5..3dfff5b06 100644 --- a/ipa-core/src/report/hybrid_info.rs +++ b/ipa-core/src/report/hybrid_info.rs @@ -20,10 +20,10 @@ impl HybridImpressionInfo { #[must_use] /// # Panics /// If report length does not fit in `u16`. - pub fn byte_len(&self) -> u16 { + pub fn byte_len(&self) -> usize { let out_len = std::mem::size_of_val(&self.key_id); debug_assert_eq!(out_len, self.to_bytes().len(), "Serialization length estimation is incorrect and leads to extra allocation or wasted memory"); - out_len.try_into().unwrap() + out_len } // Converts this instance into an owned byte slice. DO NOT USE AS INPUT TO HPKE @@ -101,9 +101,7 @@ impl HybridConversionInfo { } #[must_use] - /// # Panics - /// If report length does not fit in `u16`. - pub fn byte_len(&self) -> u16 { + pub fn byte_len(&self) -> usize { let out_len = std::mem::size_of_val(&self.key_id) + 1 // delimiter + self.conversion_site_domain.len() @@ -111,7 +109,7 @@ impl HybridConversionInfo { + std::mem::size_of_val(&self.epsilon) + std::mem::size_of_val(&self.sensitivity); debug_assert_eq!(out_len, self.to_bytes().len(), "Serialization length estimation is incorrect and leads to extra allocation or wasted memory"); - out_len.try_into().unwrap() + out_len } // Converts this instance into an owned byte slice. DO NOT USE AS INPUT TO HPKE