From cd0092add416505c947d691f2e68c5f2ee6edf17 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Tue, 30 Jan 2024 14:09:20 +0100 Subject: [PATCH] Factor out rerandomizing encryption scheme --- .../scrambledb/src/data_transformations.rs | 84 +++++++++++++++---- hacspec-scrambledb/scrambledb/src/join.rs | 7 +- hacspec-scrambledb/scrambledb/src/setup.rs | 31 +++++-- hacspec-scrambledb/scrambledb/src/split.rs | 7 +- 4 files changed, 96 insertions(+), 33 deletions(-) diff --git a/hacspec-scrambledb/scrambledb/src/data_transformations.rs b/hacspec-scrambledb/scrambledb/src/data_transformations.rs index 5896e31..7aee15d 100644 --- a/hacspec-scrambledb/scrambledb/src/data_transformations.rs +++ b/hacspec-scrambledb/scrambledb/src/data_transformations.rs @@ -13,9 +13,11 @@ use oprf::coprf::{ coprf_setup::{derive_key, BlindingPublicKey, CoPRFEvaluatorContext}, }; -use crate::{data_types::*, error::Error, setup::StoreContext}; - -use self::double_hpke::{hpke_open_level_2, hpke_seal_level_1, hpke_seal_level_2}; +use crate::{ + data_types::*, + error::Error, + setup::{StoreContext, StoreEncryptionKey}, +}; pub(crate) mod double_hpke; @@ -37,7 +39,7 @@ const PSEUDONYMIZATION_CONTEXT: &[u8] = b"CoPRF-Context-Pseudonymization"; /// level-1 encrypted. pub fn blind_identifiable_datum( bpk: &BlindingPublicKey, - ek: &[u8], + ek: &StoreEncryptionKey, datum: &IdentifiableData, randomness: &mut Randomness, ) -> Result { @@ -49,8 +51,8 @@ pub fn blind_identifiable_datum( randomness, )?); - // Level-1 encrypt data value towards receiver. - let encrypted_data_value = hpke_seal_level_1(&datum.data_value, ek, randomness)?; + // Encrypt data value towards receiver. + let encrypted_data_value = encrypt_data_value(&datum.data_value, ek, randomness)?; Ok(BlindedIdentifiableData { blinded_handle, @@ -58,6 +60,24 @@ pub fn blind_identifiable_datum( }) } +/// Encrypt a data value towards a data store. +/// +/// Inputs: +/// - `data`: The data value to encrypt. +/// - `ek`: The receiver's public encryption key. +/// - `randomness`: Random bytes +/// +/// Output: +/// A new [EncryptedDataValue], the encryption of `data`. +fn encrypt_data_value( + data: &DataValue, + ek: &StoreEncryptionKey, + randomness: &mut Randomness, +) -> Result { + let encrypted_data_value = double_hpke::hpke_seal_level_1(&data, &ek.0, randomness)?; + Ok(encrypted_data_value) +} + /// Blind a pseudonymous datum as a first step in pseudonym /// conversion. /// @@ -76,7 +96,7 @@ pub fn blind_identifiable_datum( pub fn blind_pseudonymized_datum( store_context: &StoreContext, bpk: &BlindingPublicKey, - ek: &[u8], + ek: &StoreEncryptionKey, datum: &PseudonymizedData, randomness: &mut Randomness, ) -> Result { @@ -87,8 +107,8 @@ pub fn blind_pseudonymized_datum( randomness, )?); - // Level-1 encrypt data value towards receiver. - let encrypted_data_value = hpke_seal_level_1(&datum.data_value, ek, randomness)?; + // Encrypt data value towards receiver. + let encrypted_data_value = encrypt_data_value(&datum.data_value, ek, randomness)?; Ok(BlindedPseudonymizedData { blinded_handle, @@ -112,7 +132,7 @@ pub fn blind_pseudonymized_datum( pub fn pseudonymize_blinded_datum( coprf_context: &CoPRFEvaluatorContext, bpk: &BlindingPublicKey, - ek: &[u8], + ek: &StoreEncryptionKey, datum: &BlindedIdentifiableData, randomness: &mut Randomness, ) -> Result { @@ -129,8 +149,8 @@ pub fn pseudonymize_blinded_datum( randomness, )?); - // Level-2 encrypt data value towards receiver. - let encrypted_data_value = hpke_seal_level_2(&datum.encrypted_data_value, ek, randomness)?; + // Rerandomize encrypted data value towards receiver. + let encrypted_data_value = rerandomize_encryption(&datum.encrypted_data_value, ek, randomness)?; Ok(BlindedPseudonymizedData { blinded_handle, @@ -138,6 +158,23 @@ pub fn pseudonymize_blinded_datum( }) } +/// Rerandomize the encryption of an encrypted data value. +/// +/// Inputs: +/// - `data`: The encrypted data value. +/// - `ek`: The receiver's public encryption key. +/// - `randomness`: Random bytes +/// +/// Output: +/// A new, rerandomized [EncryptedDataValue]. +fn rerandomize_encryption( + data: &EncryptedDataValue, + ek: &StoreEncryptionKey, + randomness: &mut Randomness, +) -> Result { + Ok(double_hpke::hpke_seal_level_2(&data, &ek.0, randomness)?) +} + /// Obliviously convert a blinded pseudonymous datum to a given target pseudonym key. /// /// Inputs: @@ -154,7 +191,7 @@ pub fn pseudonymize_blinded_datum( pub fn convert_blinded_datum( coprf_context: &CoPRFEvaluatorContext, bpk: &BlindingPublicKey, - ek: &[u8], + ek: &StoreEncryptionKey, conversion_target: &[u8], datum: &BlindedPseudonymizedData, randomness: &mut Randomness, @@ -177,8 +214,8 @@ pub fn convert_blinded_datum( randomness, )?); - // Level-2 encrypt data value towards receiver. - let encrypted_data_value = hpke_seal_level_2(&datum.encrypted_data_value, ek, randomness)?; + // Rerandomize encrypted data value towards receiver. + let encrypted_data_value = rerandomize_encryption(&datum.encrypted_data_value, ek, randomness)?; Ok(BlindedPseudonymizedData { blinded_handle, @@ -207,7 +244,22 @@ pub fn finalize_blinded_datum( let handle = store_context.finalize_pseudonym(datum.blinded_handle)?; // Decrypt data value for storage. - let data_value = hpke_open_level_2(&datum.encrypted_data_value, &store_context.hpke_sk)?; + let data_value = decrypt_data_value(&datum.encrypted_data_value, store_context)?; Ok(PseudonymizedData { handle, data_value }) } + +/// Decrypt an encrypted data value. +/// +/// Inputs: +/// - `data`: The value to decrypt. +/// - `store_context`: The data store's long term private state, including in particular its decryption key. +/// +/// Output: +/// The decrypted [DataValue] or an [Error] on decryption failure. +fn decrypt_data_value( + data: &EncryptedDataValue, + store_context: &StoreContext, +) -> Result { + Ok(double_hpke::hpke_open_level_2(&data, &store_context.dk.0)?) +} diff --git a/hacspec-scrambledb/scrambledb/src/join.rs b/hacspec-scrambledb/scrambledb/src/join.rs index c5b2103..4f4597f 100644 --- a/hacspec-scrambledb/scrambledb/src/join.rs +++ b/hacspec-scrambledb/scrambledb/src/join.rs @@ -1,13 +1,12 @@ //! # Pseudonym Conversion use hacspec_lib::Randomness; -use libcrux::hpke::HpkePublicKey; use oprf::coprf::coprf_setup::BlindingPublicKey; use crate::{ data_transformations::{blind_pseudonymized_datum, convert_blinded_datum}, data_types::{BlindedPseudonymizedData, PseudonymizedData}, error::Error, - setup::{ConverterContext, StoreContext}, + setup::{ConverterContext, StoreContext, StoreEncryptionKey}, table::Table, SECPAR_BYTES, }; @@ -29,7 +28,7 @@ use crate::{ pub fn blind_pseudonymous_table( store_context: &StoreContext, bpk_receiver: BlindingPublicKey, - ek_receiver: &HpkePublicKey, + ek_receiver: &StoreEncryptionKey, pseudonymized_table: Table, randomness: &mut Randomness, ) -> Result, Error> { @@ -73,7 +72,7 @@ pub fn join_identifier(identifier: String) -> String { pub fn convert_blinded_table( converter_context: &ConverterContext, bpk_receiver: BlindingPublicKey, - ek_receiver: &HpkePublicKey, + ek_receiver: &StoreEncryptionKey, table: Table, randomness: &mut Randomness, ) -> Result, Error> { diff --git a/hacspec-scrambledb/scrambledb/src/setup.rs b/hacspec-scrambledb/scrambledb/src/setup.rs index 0d41c7f..c118204 100644 --- a/hacspec-scrambledb/scrambledb/src/setup.rs +++ b/hacspec-scrambledb/scrambledb/src/setup.rs @@ -19,10 +19,17 @@ pub struct ConverterContext { pub(crate) coprf_context: CoPRFEvaluatorContext, } +/// A data store's private decryption key. +pub struct StoreDecryptionKey(pub(crate) Vec); + +/// A data store's public encryption key. +#[derive(Clone)] +pub struct StoreEncryptionKey(pub(crate) Vec); + pub struct StoreContext { coprf_receiver_context: CoPRFReceiverContext, - pub(crate) hpke_sk: Vec, - hpke_pk: Vec, + pub(crate) dk: StoreDecryptionKey, + ek: StoreEncryptionKey, k_prp: [u8; 32], } @@ -81,16 +88,14 @@ impl StoreContext { pub fn setup(randomness: &mut Randomness) -> Result { let receiver_context = CoPRFReceiverContext::new(randomness); - let HPKEConfig(_, kem, _, _) = crate::HPKE_CONF; - let (hpke_sk, hpke_pk) = - GenerateKeyPair(kem, randomness.bytes(Nsk(kem)).unwrap().to_vec())?; + let (dk, ek) = generate_store_keys(randomness)?; let k_prp = randomness.bytes(32)?.try_into()?; Ok(Self { coprf_receiver_context: receiver_context, - hpke_sk, - hpke_pk, + dk, + ek, k_prp, }) } @@ -111,8 +116,8 @@ impl StoreContext { /// let bpk = context.coprf_receiver_context.public_key() /// return (ek, bpk); /// ``` - pub fn public_keys(&self) -> (Vec, BlindingPublicKey) { - (self.hpke_pk.clone(), self.coprf_receiver_context.get_bpk()) + pub fn public_keys(&self) -> (StoreEncryptionKey, BlindingPublicKey) { + (self.ek.clone(), self.coprf_receiver_context.get_bpk()) } /// - Finalize Pseudonym: As part of the finalization of a split or join @@ -163,3 +168,11 @@ impl StoreContext { P256Point::from_raw_bytes(prp::prp(pseudonym.0, &self.k_prp)).map_err(|e| e.into()) } } + +fn generate_store_keys( + randomness: &mut Randomness, +) -> Result<(StoreDecryptionKey, StoreEncryptionKey), Error> { + let HPKEConfig(_, kem, _, _) = crate::HPKE_CONF; + let (hpke_sk, hpke_pk) = GenerateKeyPair(kem, randomness.bytes(Nsk(kem)).unwrap().to_vec())?; + Ok((StoreDecryptionKey(hpke_sk), StoreEncryptionKey(hpke_pk))) +} diff --git a/hacspec-scrambledb/scrambledb/src/split.rs b/hacspec-scrambledb/scrambledb/src/split.rs index 934c0ee..3315a73 100644 --- a/hacspec-scrambledb/scrambledb/src/split.rs +++ b/hacspec-scrambledb/scrambledb/src/split.rs @@ -1,13 +1,12 @@ //! # Pseudonymization use hacspec_lib::Randomness; -use libcrux::hpke::HpkePublicKey; use oprf::coprf::coprf_setup::BlindingPublicKey; use crate::{ data_transformations::{blind_identifiable_datum, pseudonymize_blinded_datum}, data_types::{BlindedIdentifiableData, BlindedPseudonymizedData, IdentifiableData}, error::Error, - setup::ConverterContext, + setup::{ConverterContext, StoreEncryptionKey}, table::Table, }; @@ -25,7 +24,7 @@ use crate::{ /// Outputs: /// A table of blinded identifiable data. pub fn blind_orthonymous_table( - ek_receiver: &HpkePublicKey, + ek_receiver: &StoreEncryptionKey, bpk_receiver: BlindingPublicKey, table: Table, randomness: &mut Randomness, @@ -59,7 +58,7 @@ pub fn blind_orthonymous_table( pub fn pseudonymize_blinded_table( converter_context: &ConverterContext, bpk_receiver: BlindingPublicKey, - ek_receiver: &HpkePublicKey, + ek_receiver: &StoreEncryptionKey, blinded_table: Table, randomness: &mut Randomness, ) -> Result, Error> {