From cd1c936c8a8b928994cffe06b63827dc532c0cac Mon Sep 17 00:00:00 2001 From: Alexander Wagner Date: Tue, 3 Sep 2024 15:11:52 +0200 Subject: [PATCH] WIP More throughly use SstExtension and Option --- src/hss/definitions.rs | 31 +++++-------------- src/hss/reference_impl_private_key.rs | 36 +++++++++++----------- src/lms/definitions.rs | 4 +-- src/sst/gen_key.rs | 23 +++++++------- src/sst/parameters.rs | 44 +++++++++++++++------------ 5 files changed, 64 insertions(+), 74 deletions(-) diff --git a/src/hss/definitions.rs b/src/hss/definitions.rs index 67b99772..a540df41 100644 --- a/src/hss/definitions.rs +++ b/src/hss/definitions.rs @@ -20,7 +20,6 @@ use crate::{ signing::LmsSignature, }, sst::helper::get_subtree_node_idx, - sst::parameters::SstExtension, util::helper::read_and_advance, }; @@ -59,23 +58,13 @@ impl HssPrivateKey { let parameters = private_key.compressed_parameter.to::()?; let used_leafs_indexes = private_key.compressed_used_leafs_indexes.to(¶meters); - let sst_ext_option = SstExtension { - signing_entity_idx: private_key.sst_ext.signing_entity_idx, - l0_top_div: private_key.sst_ext.l0_top_div, - }; - let sst_ext_option = if sst_ext != SstExtension::default() { - Some(sst_ext) - } else { - None - }; - let lms_private_key = LmsPrivateKey { seed: current_seed.seed.clone(), lms_tree_identifier: current_seed.lms_tree_identifier, lmots_parameter: *parameters[0].get_lmots_parameter(), lms_parameter: *parameters[0].get_lms_parameter(), used_leafs_index: used_leafs_indexes[0], - sst_ext: sst_ext_option, + sst_ext: private_key.sst_option.clone(), }; hss_private_key.private_key.push(lms_private_key); @@ -126,11 +115,10 @@ impl HssPrivateKey { return hss_expand_aux_data::(Some(aux_data), Some(private_key.seed.as_slice())); } - let l0_top_div = private_key.sst_ext.l0_top_div; - let opt_l0_top_div = if 0 == l0_top_div { - None + let opt_l0_top_div = if let Some(sst_extension) = &private_key.sst_option { + Some(sst_extension.l0_top_div()) } else { - Some(l0_top_div) + None }; // Shrink input slice @@ -238,12 +226,9 @@ impl HssPublicKey { intermed_nodes: &ArrayVec<[ArrayVec<[u8; MAX_HASH_SIZE]>; MAX_SSTS_SIGNING_ENTITIES]>, tree_identifier: &[u8; ILEN], ) -> Result { - if private_key.sst_ext.signing_entity_idx == 0 || private_key.sst_ext.l0_top_div == 0 { - return Err(()); - }; + let sst_option = private_key.sst_option.clone().ok_or(())?; let parameters = private_key.compressed_parameter.to::()?; - let levels = parameters.len(); let used_leafs_indexes = private_key.compressed_used_leafs_indexes.to(¶meters); let top_lms_parameter = parameters[0].get_lms_parameter(); @@ -273,13 +258,13 @@ impl HssPublicKey { // TODO/Rework: how do we get rid of those repeated "if let Some"? // Additions for SSTS: add "intermediate node values" from other signing entities to AUX data if let Some(expanded_aux_data) = opt_expanded_aux_data.as_mut() { - let num_signing_entities = 2usize.pow(private_key.sst_ext.l0_top_div as u32); + let num_signing_entities = 2usize.pow(sst_option.l0_top_div() as u32); for si in 1..=num_signing_entities as u8 { // node index of SI intermed node in whole tree: let idx: usize = get_subtree_node_idx( si, top_lms_parameter.get_tree_height(), - private_key.sst_ext.l0_top_div, + sst_option.l0_top_div(), ) as usize; hss_save_aux_data::( expanded_aux_data, @@ -306,7 +291,7 @@ impl HssPublicKey { Ok(Self { public_key: lms_keypair.public_key, - level: levels, + level: parameters.len(), }) } diff --git a/src/hss/reference_impl_private_key.rs b/src/hss/reference_impl_private_key.rs index e10a00aa..0c7123da 100644 --- a/src/hss/reference_impl_private_key.rs +++ b/src/hss/reference_impl_private_key.rs @@ -85,12 +85,12 @@ impl SeedAndLmsTreeIdentifier { } } -#[derive(Clone, Default, PartialEq, Eq, Zeroize, ZeroizeOnDrop)] +#[derive(Default, PartialEq, Eq, Zeroize, ZeroizeOnDrop)] pub struct ReferenceImplPrivateKey { pub compressed_used_leafs_indexes: CompressedUsedLeafsIndexes, pub compressed_parameter: CompressedParameterSet, - pub sst_ext: SstExtension, pub seed: Seed, + pub sst_option: Option, } impl ReferenceImplPrivateKey { @@ -98,25 +98,25 @@ impl ReferenceImplPrivateKey { self.seed = Seed::default(); self.compressed_parameter = CompressedParameterSet::default(); self.compressed_used_leafs_indexes = CompressedUsedLeafsIndexes::new(0); + self.sst_option = None; } pub fn generate( parameters: &[HssParameter], seed: &Seed, - sst_extension: Option, + sst_option: Option, ) -> Result { - let sst_ext = sst_extension.unwrap_or_default(); - let top_lms_parameter = parameters[0].get_lms_parameter(); - let mut used_leafs_index: u32 = 0; - if sst_ext.l0_top_div != 0 { - used_leafs_index = helper::get_sst_first_leaf_idx( - sst_ext.signing_entity_idx, + let used_leafs_index = if let Some(sst_extension) = &sst_option { + helper::get_sst_first_leaf_idx( + sst_extension.signing_entity_idx(), top_lms_parameter.get_tree_height(), - sst_ext.l0_top_div, - ); - } + sst_extension.l0_top_div(), + ) + } else { + 0 + }; let mut arr: [u32; MAX_ALLOWED_HSS_LEVELS] = [0; MAX_ALLOWED_HSS_LEVELS]; arr[0] = used_leafs_index; @@ -124,8 +124,8 @@ impl ReferenceImplPrivateKey { let private_key: ReferenceImplPrivateKey = ReferenceImplPrivateKey { compressed_used_leafs_indexes: CompressedUsedLeafsIndexes::from(&arr, parameters), compressed_parameter: CompressedParameterSet::from(parameters)?, - sst_ext, seed: seed.clone(), + sst_option, }; Ok(private_key) @@ -134,9 +134,9 @@ impl ReferenceImplPrivateKey { pub fn to_binary_representation(&self) -> ArrayVec<[u8; IMPL_MAX_PRIVATE_KEY_SIZE]> { let mut result = ArrayVec::new(); - if self.sst_ext != SstExtension::default() { - result.extend_from_slice(&self.sst_ext.signing_entity_idx.to_be_bytes()); - result.extend_from_slice(&self.sst_ext.l0_top_div.to_be_bytes()); + if let Some(sst_extension) = &self.sst_option { + result.extend_from_slice(&sst_extension.signing_entity_idx().to_be_bytes()); + result.extend_from_slice(&sst_extension.l0_top_div().to_be_bytes()); } result.extend_from_slice(&self.compressed_used_leafs_indexes.count.to_be_bytes()); result.extend_from_slice(&self.compressed_parameter.0); @@ -157,8 +157,8 @@ impl ReferenceImplPrivateKey { let mut index = 0; if data.len() == SST_IMPL_MAX_PRIVATE_KEY_SIZE - MAX_SEED_LEN + H::OUTPUT_SIZE as usize { - let ssts_ext = read_and_advance(data, SST_SIZE, &mut index); - result.sst_ext = SstExtension::from_slice(ssts_ext)?; + let sst_ext = read_and_advance(data, SST_SIZE, &mut index); + result.sst_option = SstExtension::from_slice(sst_ext).ok(); } let compressed_used_leafs_indexes = diff --git a/src/lms/definitions.rs b/src/lms/definitions.rs index de71d995..397d7147 100644 --- a/src/lms/definitions.rs +++ b/src/lms/definitions.rs @@ -52,9 +52,9 @@ impl LmsPrivateKey { if let Some(my_sst_ext) = &self.sst_ext { // our last leafs function returns 0..total_num-1, but here we need 1..total_num 1 + get_sst_last_leaf_idx( - my_sst_ext.signing_entity_idx, + my_sst_ext.signing_entity_idx(), self.lms_parameter.get_tree_height(), - my_sst_ext.l0_top_div, + my_sst_ext.l0_top_div(), ) } else { self.lms_parameter.number_of_lm_ots_keys() as u32 diff --git a/src/sst/gen_key.rs b/src/sst/gen_key.rs index 302b77ba..f1225602 100644 --- a/src/sst/gen_key.rs +++ b/src/sst/gen_key.rs @@ -27,10 +27,11 @@ pub fn prepare_sst_keygen( if sst_param.get_signing_entity_idx() == 0 || sst_param.get_l0_top_div() == 0 { return Err(Error::new()); } - let sst_ext = Some(SstExtension { - signing_entity_idx: sst_param.get_signing_entity_idx(), - l0_top_div: sst_param.get_l0_top_div(), - }); + let sst_ext = SstExtension::new( + sst_param.get_signing_entity_idx(), + sst_param.get_l0_top_div(), + ) + .ok(); // create two representations of private keys because we need their data elements // -> ReferenceImplPrivateKey and SigningKey @@ -74,12 +75,7 @@ pub fn prepare_sst_keygen( .clone_from_slice(tree_identifier); } - let sst_ext = SstExtension { - signing_entity_idx: rfc_private_key.sst_ext.signing_entity_idx, - l0_top_div: rfc_private_key.sst_ext.l0_top_div, - }; - - let sst_ext_option = Some(sst_ext); + let sst_option = rfc_private_key.sst_option.clone(); let our_node_index = get_subtree_node_idx( sst_param.get_signing_entity_idx(), @@ -95,7 +91,7 @@ pub fn prepare_sst_keygen( used_leafs_index, // actually not used in "get_tree_element", irrelevant *sst_param.get_hss_parameters()[0].get_lmots_parameter(), *sst_param.get_hss_parameters()[0].get_lms_parameter(), - sst_ext_option, + sst_option, ); let our_intermed_node_value = get_tree_element( @@ -114,7 +110,8 @@ pub fn get_num_signing_entities(private_key: &[u8]) -> Result::from_binary_representation(private_key) .map_err(|_| Error::new())?; - let num_signing_entities = 2u32.pow(rfc_private_key.sst_ext.l0_top_div as u32); + let num_signing_entities = + 2u32.pow(rfc_private_key.sst_option.clone().unwrap().l0_top_div() as u32); Ok(num_signing_entities) } @@ -136,3 +133,5 @@ pub fn finalize_sst_keygen( Ok(verifying_key) } + +//TODO tests needed diff --git a/src/sst/parameters.rs b/src/sst/parameters.rs index aa2fc822..4aee4226 100644 --- a/src/sst/parameters.rs +++ b/src/sst/parameters.rs @@ -6,13 +6,9 @@ use zeroize::{Zeroize, ZeroizeOnDrop}; #[derive(Clone, PartialEq, Eq)] pub struct SstsParameter { hss_parameters: ArrayVec<[HssParameter; constants::REF_IMPL_MAX_ALLOWED_HSS_LEVELS]>, - // TODO/Rework: use SstExtension? - l0_top_div: u8, - signing_entity_idx: u8, + sst_extension: SstExtension, } -impl Copy for SstsParameter {} - impl SstsParameter { pub fn new( hss_params: ArrayVec<[HssParameter; constants::REF_IMPL_MAX_ALLOWED_HSS_LEVELS]>, @@ -21,8 +17,7 @@ impl SstsParameter { ) -> Self { SstsParameter { hss_parameters: hss_params, - l0_top_div, - signing_entity_idx, + sst_extension: SstExtension::new(signing_entity_idx, l0_top_div).unwrap(), } } @@ -33,32 +28,43 @@ impl SstsParameter { } pub fn get_l0_top_div(&self) -> u8 { - self.l0_top_div + self.sst_extension.l0_top_div() } pub fn get_signing_entity_idx(&self) -> u8 { - self.signing_entity_idx + self.sst_extension.signing_entity_idx() } } -#[derive(Debug, Default, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)] +#[derive(Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)] pub struct SstExtension { - pub signing_entity_idx: u8, // from 1 to (2^l0_top_div) - pub l0_top_div: u8, // e.g. L-0 LMS height of 5 and l0_top_div = 3: division top/bottom is 3/2 -> 2^3 = 8 signing entities + signing_entity_idx: u8, // from 1 to (2^l0_top_div) + l0_top_div: u8, // e.g. L-0 LMS height of 5 and l0_top_div = 3: division top/bottom is 3/2 -> 2^3 = 8 signing entities } impl SstExtension { - // TODO/Review: unlike in all other locations, clippy reports - // "this returns a `Result<_, ()>`" and "use a custom `Error` type instead" - // see "Result" in "hss/reference_impl_private_key.rs" -> CompressedParameterSet + pub fn new(signing_entity_idx: u8, l0_top_div: u8) -> Result { + if signing_entity_idx == 0 || l0_top_div == 0 { + return Err(()); + } + Ok(Self { + signing_entity_idx, + l0_top_div, + }) + } + pub fn from_slice(data: &[u8]) -> Result { if data.len() != constants::SST_SIZE { return Err(()); } + Self::new(data[0], data[1]) + } - Ok(SstExtension { - signing_entity_idx: data[0], - l0_top_div: data[1], - }) + pub fn signing_entity_idx(&self) -> u8 { + self.signing_entity_idx + } + + pub fn l0_top_div(&self) -> u8 { + self.l0_top_div } }