Skip to content

Commit

Permalink
stuff works O.o
Browse files Browse the repository at this point in the history
  • Loading branch information
tyurek committed Dec 11, 2024
1 parent 35160ea commit e3daf23
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 46 deletions.
28 changes: 20 additions & 8 deletions ipa-core/src/cli/crypto/hybrid_decrypt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ use crate::{
U128Conversions,
},
hpke::{KeyRegistry, PrivateKeyOnly},
report::hybrid::{EncryptedHybridReport, HybridReport},
report::{
hybrid::{EncryptedHybridReport, HybridReport},
hybrid_info::HybridInfo,
},
test_fixture::Reconstruct,
};

Expand Down Expand Up @@ -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),
Expand All @@ -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),
Expand All @@ -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");
Expand All @@ -166,17 +177,18 @@ struct DecryptedHybridReports {
}

impl Iterator for DecryptedHybridReports {
type Item = HybridReport<BA8, BA3>;
type Item = (HybridReport<BA8, BA3>, HybridInfo);

fn next(&mut self) -> Option<Self::Item> {
let mut line = String::new();
if self.reader.read_line(&mut line).unwrap() > 0 {
let encrypted_report_bytes = hex::decode(line.trim()).unwrap();
let enc_report =
EncryptedHybridReport::from_bytes(encrypted_report_bytes.into()).unwrap();
let dec_report: HybridReport<BA8, BA3> =
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
}
Expand Down
23 changes: 18 additions & 5 deletions ipa-core/src/cli/crypto/hybrid_encrypt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<BreakdownKey, TriggerValue>);
type EncryptorInput = (
usize,
usize,
HybridReport<BreakdownKey, TriggerValue>,
HybridInfo,
);
/// Encryptor sends report id and encrypted bytes down to file worker to write those bytes
/// down
type EncryptorOutput = (usize, Vec<u8>);
Expand Down Expand Up @@ -91,7 +99,8 @@ impl HybridEncryptArgs {

let mut worker_pool = ReportWriter::new(key_registries, &self.output_dir);
for (report_id, record) in input.iter::<TestHybridRecord>().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()?;
Expand Down Expand Up @@ -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))?;
Expand Down Expand Up @@ -206,9 +216,12 @@ impl ReportWriter {
&mut self,
report_id: usize,
shares: [HybridReport<BreakdownKey, TriggerValue>; 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(())
Expand Down
105 changes: 82 additions & 23 deletions ipa-core/src/report/hybrid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down Expand Up @@ -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<P: PrivateKeyRegistry>(
pub fn decrypt_and_return_info<P: PrivateKeyRegistry>(
&self,
key_registry: &P,
) -> Result<HybridImpressionReport<BK>, InvalidHybridReportError> {
) -> Result<(HybridImpressionReport<BK>, HybridImpressionInfo), InvalidHybridReportError> {
type CTMKLength = Sum<<Replicated<BA64> as Serializable>::Size, TagSize>;
type CTBTTLength<BK> = <<Replicated<BK> as Serializable>::Size as Add<TagSize>>::Output;

Expand All @@ -605,16 +605,35 @@ where

let plaintext_btt = open_in_place(sk, self.encap_key_btt(), &mut ct_btt, &info_enc_bytes)?;

Ok(HybridImpressionReport::<BK> {
match_key: Replicated::<BA64>::deserialize_infallible(GenericArray::from_slice(
plaintext_mk,
)),
breakdown_key: Replicated::<BK>::deserialize(GenericArray::from_slice(plaintext_btt))
Ok((
HybridImpressionReport::<BK> {
match_key: Replicated::<BA64>::deserialize_infallible(GenericArray::from_slice(
plaintext_mk,
)),
breakdown_key: Replicated::<BK>::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<P: PrivateKeyRegistry>(
&self,
key_registry: &P,
) -> Result<HybridImpressionReport<BK>, InvalidHybridReportError> {
let (report, _) = self.decrypt_and_return_info(key_registry)?;
Ok(report)
}
}

Expand Down Expand Up @@ -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<P: PrivateKeyRegistry>(
pub fn decrypt_and_return_info<P: PrivateKeyRegistry>(
&self,
key_registry: &P,
) -> Result<HybridConversionReport<V>, InvalidHybridReportError> {
) -> Result<(HybridConversionReport<V>, HybridConversionInfo), InvalidHybridReportError> {
type CTMKLength = Sum<<Replicated<BA64> as Serializable>::Size, TagSize>;
type CTBTTLength<V> = <<Replicated<V> as Serializable>::Size as Add<TagSize>>::Output;

Expand All @@ -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::<V> {
match_key: Replicated::<BA64>::deserialize_infallible(GenericArray::from_slice(
plaintext_mk,
)),
value: Replicated::<V>::deserialize(GenericArray::from_slice(plaintext_btt)).map_err(
|e| InvalidHybridReportError::DeserializationError("trigger_value", e.into()),
)?,
//info,
})
Ok((
HybridConversionReport::<V> {
match_key: Replicated::<BA64>::deserialize_infallible(GenericArray::from_slice(
plaintext_mk,
)),
value: Replicated::<V>::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<P: PrivateKeyRegistry>(
&self,
key_registry: &P,
) -> Result<HybridConversionReport<V>, InvalidHybridReportError> {
let (report, _) = self.decrypt_and_return_info(key_registry)?;
Ok(report)
}
}

Expand Down Expand Up @@ -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<P: PrivateKeyRegistry>(
&self,
key_registry: &P,
) -> Result<(HybridReport<BK, V>, 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).
Expand Down
28 changes: 28 additions & 0 deletions ipa-core/src/report/hybrid_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,34 @@ impl HybridInfo {
}
}

impl From<HybridImpressionInfo> 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<HybridConversionInfo> 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::*;
Expand Down
19 changes: 9 additions & 10 deletions ipa-core/src/test_fixture/hybrid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ where
}

impl TestHybridRecord {
#[must_use]
pub fn create_hybrid_info(&self) -> HybridInfo {
match self {
TestHybridRecord::TestImpression {
Expand All @@ -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,
Expand All @@ -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,
Expand Down

0 comments on commit e3daf23

Please sign in to comment.