diff --git a/key_protocol/src/key_management/key_tree/chain_index.rs b/key_protocol/src/key_management/key_tree/chain_index.rs new file mode 100644 index 0000000..dad9b2a --- /dev/null +++ b/key_protocol/src/key_management/key_tree/chain_index.rs @@ -0,0 +1,115 @@ +use std::str::FromStr; + +use serde::{Deserialize, Serialize}; + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize)] +pub struct ChainIndex(Vec); + +impl FromStr for ChainIndex { + type Err = hex::FromHexError; + + fn from_str(s: &str) -> Result { + if s.is_empty() { + return Ok(Self(vec![])); + } + + let hex_decoded = hex::decode(s)?; + + if !hex_decoded.len().is_multiple_of(4) { + Err(hex::FromHexError::InvalidStringLength) + } else { + let mut res_vec = vec![]; + + for i in 0..(hex_decoded.len() / 4) { + res_vec.push(u32::from_le_bytes([ + hex_decoded[4 * i], + hex_decoded[4 * i + 1], + hex_decoded[4 * i + 2], + hex_decoded[4 * i + 3], + ])); + } + + Ok(Self(res_vec)) + } + } +} + +#[allow(clippy::to_string_trait_impl)] +impl ToString for ChainIndex { + fn to_string(&self) -> String { + if self.0.is_empty() { + return "".to_string(); + } + + let mut res_vec = vec![]; + + for index in &self.0 { + res_vec.extend_from_slice(&index.to_le_bytes()); + } + + hex::encode(res_vec) + } +} + +impl ChainIndex { + pub fn root() -> Self { + ChainIndex::from_str("").unwrap() + } + + pub fn chain(&self) -> &[u32] { + &self.0 + } + + pub fn next_in_line(&self) -> ChainIndex { + let mut chain = self.0.clone(); + //ToDo: Add overflow check + if let Some(last_p) = chain.last_mut() { + *last_p += 1 + } + + ChainIndex(chain) + } + + pub fn n_th_child(&self, child_id: u32) -> ChainIndex { + let mut chain = self.0.clone(); + chain.push(child_id); + + ChainIndex(chain) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_chain_id_root_correct() { + let chain_id = ChainIndex::root(); + let chain_id_2 = ChainIndex::from_str("").unwrap(); + + assert_eq!(chain_id, chain_id_2); + } + + #[test] + fn test_chain_id_deser_correct() { + let chain_id = ChainIndex::from_str("01010000").unwrap(); + + assert_eq!(chain_id.chain(), &[257]); + } + + #[test] + fn test_chain_id_next_in_line_correct() { + let chain_id = ChainIndex::from_str("01010000").unwrap(); + let next_in_line = chain_id.next_in_line(); + + assert_eq!(next_in_line, ChainIndex::from_str("02010000").unwrap()); + } + + #[test] + fn test_chain_id_child_correct() { + let chain_id = ChainIndex::from_str("01010000").unwrap(); + let child = chain_id.n_th_child(3); + + assert_eq!(child, ChainIndex::from_str("0101000003000000").unwrap()); + } +} diff --git a/key_protocol/src/key_management/key_tree/keys_private.rs b/key_protocol/src/key_management/key_tree/keys_private.rs new file mode 100644 index 0000000..46ade9f --- /dev/null +++ b/key_protocol/src/key_management/key_tree/keys_private.rs @@ -0,0 +1,201 @@ +use k256::{Scalar, elliptic_curve::PrimeField}; +use nssa_core::{NullifierPublicKey, NullifierSecretKey, encryption::IncomingViewingPublicKey}; +use serde::{Deserialize, Serialize}; + +use crate::key_management::{ + key_tree::traits::KeyNode, + secret_holders::{IncomingViewingSecretKey, OutgoingViewingSecretKey, SecretSpendingKey}, +}; + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct ChildKeysPrivate { + pub ssk: SecretSpendingKey, + pub nsk: NullifierSecretKey, + pub isk: IncomingViewingSecretKey, + pub ovk: OutgoingViewingSecretKey, + pub npk: NullifierPublicKey, + pub ipk: IncomingViewingPublicKey, + pub ccc: [u8; 32], + ///Can be None if root + pub cci: Option, + pub account: nssa::Account, +} + +impl KeyNode for ChildKeysPrivate { + fn root(seed: [u8; 64]) -> Self { + let hash_value = hmac_sha512::HMAC::mac(seed, "NSSA_master_priv"); + + let ssk = SecretSpendingKey(*hash_value.first_chunk::<32>().unwrap()); + let ccc = *hash_value.last_chunk::<32>().unwrap(); + + let nsk = ssk.generate_nullifier_secret_key(); + let isk = ssk.generate_incoming_viewing_secret_key(); + let ovk = ssk.generate_outgoing_viewing_secret_key(); + + let npk = (&nsk).into(); + let ipk = IncomingViewingPublicKey::from_scalar(isk); + + Self { + ssk, + nsk, + isk, + ovk, + npk, + ipk, + ccc, + cci: None, + account: nssa::Account::default(), + } + } + + fn n_th_child(&self, cci: u32) -> Self { + let parent_pt = Scalar::from_repr(self.ovk.into()).unwrap() + + Scalar::from_repr(self.nsk.into()).unwrap() + * Scalar::from_repr(self.isk.into()).unwrap(); + let mut input = vec![]; + + input.extend_from_slice(b"NSSA_seed_priv"); + input.extend_from_slice(&parent_pt.to_bytes()); + input.extend_from_slice(&cci.to_le_bytes()); + + let hash_value = hmac_sha512::HMAC::mac(input, self.ccc); + + let ssk = SecretSpendingKey(*hash_value.first_chunk::<32>().unwrap()); + let ccc = *hash_value.last_chunk::<32>().unwrap(); + + let nsk = ssk.generate_nullifier_secret_key(); + let isk = ssk.generate_incoming_viewing_secret_key(); + let ovk = ssk.generate_outgoing_viewing_secret_key(); + + let npk = (&nsk).into(); + let ipk = IncomingViewingPublicKey::from_scalar(isk); + + Self { + ssk, + nsk, + isk, + ovk, + npk, + ipk, + ccc, + cci: Some(cci), + account: nssa::Account::default(), + } + } + + fn chain_code(&self) -> &[u8; 32] { + &self.ccc + } + + fn child_index(&self) -> &Option { + &self.cci + } + + fn address(&self) -> nssa::Address { + nssa::Address::from(&self.npk) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_keys_deterministic_generation() { + let root_keys = ChildKeysPrivate::root([42; 64]); + let child_keys = root_keys.n_th_child(5); + + assert_eq!(root_keys.cci, None); + assert_eq!(child_keys.cci, Some(5)); + + assert_eq!( + root_keys.ssk.0, + [ + 249, 83, 253, 32, 174, 204, 185, 44, 253, 167, 61, 92, 128, 5, 152, 4, 220, 21, 88, + 84, 167, 180, 154, 249, 44, 77, 33, 136, 59, 131, 203, 152 + ] + ); + assert_eq!( + child_keys.ssk.0, + [ + 16, 242, 229, 242, 252, 158, 153, 210, 234, 120, 70, 85, 83, 196, 5, 53, 28, 26, + 187, 230, 22, 193, 146, 232, 237, 3, 166, 184, 122, 1, 233, 93 + ] + ); + + assert_eq!( + root_keys.nsk, + [ + 38, 195, 52, 182, 16, 66, 167, 156, 9, 14, 65, 100, 17, 93, 166, 71, 27, 148, 93, + 85, 116, 109, 130, 8, 195, 222, 159, 214, 141, 41, 124, 57 + ] + ); + assert_eq!( + child_keys.nsk, + [ + 215, 46, 2, 151, 174, 60, 86, 154, 5, 3, 175, 245, 12, 176, 220, 58, 250, 118, 236, + 49, 254, 221, 229, 58, 40, 1, 170, 145, 175, 108, 23, 170 + ] + ); + + assert_eq!( + root_keys.isk, + [ + 153, 161, 15, 34, 96, 184, 165, 165, 27, 244, 155, 40, 70, 5, 241, 133, 78, 40, 61, + 118, 48, 148, 226, 5, 97, 18, 201, 128, 82, 248, 163, 72 + ] + ); + assert_eq!( + child_keys.isk, + [ + 192, 155, 55, 43, 164, 115, 71, 145, 227, 225, 21, 57, 55, 12, 226, 44, 10, 103, + 39, 73, 230, 173, 60, 69, 69, 122, 110, 241, 164, 3, 192, 57 + ] + ); + + assert_eq!( + root_keys.ovk, + [ + 205, 87, 71, 129, 90, 242, 217, 200, 140, 252, 124, 46, 207, 7, 33, 156, 83, 166, + 150, 81, 98, 131, 182, 156, 110, 92, 78, 140, 125, 218, 152, 154 + ] + ); + assert_eq!( + child_keys.ovk, + [ + 131, 202, 219, 172, 219, 29, 48, 120, 226, 209, 209, 10, 216, 173, 48, 167, 233, + 17, 35, 155, 30, 217, 176, 120, 72, 146, 250, 226, 165, 178, 255, 90 + ] + ); + + assert_eq!( + root_keys.npk.0, + [ + 65, 176, 149, 243, 192, 45, 216, 177, 169, 56, 229, 7, 28, 66, 204, 87, 109, 83, + 152, 64, 14, 188, 179, 210, 147, 60, 22, 251, 203, 70, 89, 215 + ] + ); + assert_eq!( + child_keys.npk.0, + [ + 69, 104, 130, 115, 48, 134, 19, 188, 67, 148, 163, 54, 155, 237, 57, 27, 136, 228, + 111, 233, 205, 158, 149, 31, 84, 11, 241, 176, 243, 12, 138, 249 + ] + ); + + assert_eq!( + root_keys.ipk.0, + &[ + 3, 174, 56, 136, 244, 179, 18, 122, 38, 220, 36, 50, 200, 41, 104, 167, 70, 18, 60, + 202, 93, 193, 29, 16, 125, 252, 96, 51, 199, 152, 47, 233, 178 + ] + ); + assert_eq!( + child_keys.ipk.0, + &[ + 3, 18, 202, 246, 79, 141, 169, 51, 55, 202, 120, 169, 244, 201, 156, 162, 216, 115, + 126, 53, 46, 94, 235, 125, 114, 178, 215, 81, 171, 93, 93, 88, 117 + ] + ); + } +} diff --git a/key_protocol/src/key_management/key_tree/keys_public.rs b/key_protocol/src/key_management/key_tree/keys_public.rs new file mode 100644 index 0000000..4e1bf1e --- /dev/null +++ b/key_protocol/src/key_management/key_tree/keys_public.rs @@ -0,0 +1,119 @@ +use serde::{Deserialize, Serialize}; + +use crate::key_management::key_tree::traits::KeyNode; + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct ChildKeysPublic { + pub csk: nssa::PrivateKey, + pub cpk: nssa::PublicKey, + pub ccc: [u8; 32], + ///Can be None if root + pub cci: Option, +} + +impl KeyNode for ChildKeysPublic { + fn root(seed: [u8; 64]) -> Self { + let hash_value = hmac_sha512::HMAC::mac(seed, "NSSA_master_pub"); + + let csk = nssa::PrivateKey::try_new(*hash_value.first_chunk::<32>().unwrap()).unwrap(); + let ccc = *hash_value.last_chunk::<32>().unwrap(); + let cpk = nssa::PublicKey::new_from_private_key(&csk); + + Self { + csk, + cpk, + ccc, + cci: None, + } + } + + fn n_th_child(&self, cci: u32) -> Self { + let mut hash_input = vec![]; + hash_input.extend_from_slice(self.csk.value()); + hash_input.extend_from_slice(&cci.to_le_bytes()); + + let hash_value = hmac_sha512::HMAC::mac(&hash_input, self.ccc); + + let csk = nssa::PrivateKey::try_new(*hash_value.first_chunk::<32>().unwrap()).unwrap(); + let ccc = *hash_value.last_chunk::<32>().unwrap(); + let cpk = nssa::PublicKey::new_from_private_key(&csk); + + Self { + csk, + cpk, + ccc, + cci: Some(cci), + } + } + + fn chain_code(&self) -> &[u8; 32] { + &self.ccc + } + + fn child_index(&self) -> &Option { + &self.cci + } + + fn address(&self) -> nssa::Address { + nssa::Address::from(&self.cpk) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_keys_deterministic_generation() { + let root_keys = ChildKeysPublic::root([42; 64]); + let child_keys = root_keys.n_th_child(5); + + assert_eq!(root_keys.cci, None); + assert_eq!(child_keys.cci, Some(5)); + + assert_eq!( + root_keys.ccc, + [ + 61, 30, 91, 26, 133, 91, 236, 192, 231, 53, 186, 139, 11, 221, 202, 11, 178, 215, + 254, 103, 191, 60, 117, 112, 1, 226, 31, 156, 83, 104, 150, 224 + ] + ); + assert_eq!( + child_keys.ccc, + [ + 67, 26, 102, 68, 189, 155, 102, 80, 199, 188, 112, 142, 207, 157, 36, 210, 48, 224, + 35, 6, 112, 180, 11, 190, 135, 218, 9, 14, 84, 231, 58, 98 + ] + ); + + assert_eq!( + root_keys.csk.value(), + &[ + 241, 82, 246, 237, 62, 130, 116, 47, 189, 112, 99, 67, 178, 40, 115, 245, 141, 193, + 77, 164, 243, 76, 222, 64, 50, 146, 23, 145, 91, 164, 92, 116 + ] + ); + assert_eq!( + child_keys.csk.value(), + &[ + 11, 151, 27, 212, 167, 26, 77, 234, 103, 145, 53, 191, 184, 25, 240, 191, 156, 25, + 60, 144, 65, 22, 193, 163, 246, 227, 212, 81, 49, 170, 33, 158 + ] + ); + + assert_eq!( + root_keys.cpk.value(), + &[ + 220, 170, 95, 177, 121, 37, 86, 166, 56, 238, 232, 72, 21, 106, 107, 217, 158, 74, + 133, 91, 143, 244, 155, 15, 2, 230, 223, 169, 13, 20, 163, 138 + ] + ); + assert_eq!( + child_keys.cpk.value(), + &[ + 152, 249, 236, 111, 132, 96, 184, 122, 21, 179, 240, 15, 234, 155, 164, 144, 108, + 110, 120, 74, 176, 147, 196, 168, 243, 186, 203, 79, 97, 17, 194, 52 + ] + ); + } +} diff --git a/key_protocol/src/key_management/key_tree.rs b/key_protocol/src/key_management/key_tree/mod.rs similarity index 56% rename from key_protocol/src/key_management/key_tree.rs rename to key_protocol/src/key_management/key_tree/mod.rs index dd59363..c21cc6e 100644 --- a/key_protocol/src/key_management/key_tree.rs +++ b/key_protocol/src/key_management/key_tree/mod.rs @@ -1,143 +1,35 @@ -use std::{ - collections::{BTreeMap, HashMap}, - str::FromStr, +use std::collections::{BTreeMap, HashMap}; + +use serde::{Deserialize, Serialize}; + +use crate::key_management::{ + key_tree::{ + chain_index::ChainIndex, keys_private::ChildKeysPrivate, keys_public::ChildKeysPublic, + traits::KeyNode, + }, + secret_holders::SeedHolder, }; -use crate::key_management::secret_holders::SeedHolder; +pub mod chain_index; +pub mod keys_private; +pub mod keys_public; +pub mod traits; -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] -pub struct ChainIndex(Vec); - -impl FromStr for ChainIndex { - type Err = hex::FromHexError; - - fn from_str(s: &str) -> Result { - if s.is_empty() { - return Ok(Self(vec![])); - } - - let hex_decoded = hex::decode(s)?; - - if !hex_decoded.len().is_multiple_of(4) { - Err(hex::FromHexError::InvalidStringLength) - } else { - let mut res_vec = vec![]; - - for i in 0..(hex_decoded.len() / 4) { - res_vec.push(u32::from_le_bytes([ - hex_decoded[4 * i], - hex_decoded[4 * i + 1], - hex_decoded[4 * i + 2], - hex_decoded[4 * i + 3], - ])); - } - - Ok(Self(res_vec)) - } - } -} - -#[allow(clippy::to_string_trait_impl)] -impl ToString for ChainIndex { - fn to_string(&self) -> String { - if self.0.is_empty() { - return "".to_string(); - } - - let mut res_vec = vec![]; - - for index in &self.0 { - res_vec.extend_from_slice(&index.to_le_bytes()); - } - - hex::encode(res_vec) - } -} - -impl ChainIndex { - pub fn root() -> Self { - ChainIndex::from_str("").unwrap() - } - - pub fn chain(&self) -> &[u32] { - &self.0 - } - - pub fn next_in_line(&self) -> ChainIndex { - let mut chain = self.0.clone(); - //ToDo: Add overflow check - if let Some(last_p) = chain.last_mut() { - *last_p += 1 - } - - ChainIndex(chain) - } - - pub fn n_th_child(&self, child_id: u32) -> ChainIndex { - let mut chain = self.0.clone(); - chain.push(child_id); - - ChainIndex(chain) - } -} - -#[derive(Debug)] -pub struct ChildKeysPublic { - pub csk: nssa::PrivateKey, - pub cpk: nssa::PublicKey, - pub ccc: [u8; 32], - ///Can be None if root - pub cci: Option, -} - -impl ChildKeysPublic { - pub fn root(seed: [u8; 64]) -> Self { - let hash_value = hmac_sha512::HMAC::mac(seed, "NSSA_master_pub"); - - let csk = nssa::PrivateKey::try_new(*hash_value.first_chunk::<32>().unwrap()).unwrap(); - let ccc = *hash_value.last_chunk::<32>().unwrap(); - let cpk = nssa::PublicKey::new_from_private_key(&csk); - - Self { - csk, - cpk, - ccc, - cci: None, - } - } - - pub fn n_th_child(&self, cci: u32) -> Self { - let mut hash_input = vec![]; - hash_input.extend_from_slice(self.csk.value()); - hash_input.extend_from_slice(&cci.to_le_bytes()); - - let hash_value = hmac_sha512::HMAC::mac(&hash_input, self.ccc); - - let csk = nssa::PrivateKey::try_new(*hash_value.first_chunk::<32>().unwrap()).unwrap(); - let ccc = *hash_value.last_chunk::<32>().unwrap(); - let cpk = nssa::PublicKey::new_from_private_key(&csk); - - Self { - csk, - cpk, - ccc, - cci: Some(cci), - } - } -} - -#[derive(Debug)] -pub struct KeyTreePublic { - pub key_map: BTreeMap, +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct KeyTree { + pub key_map: BTreeMap, pub addr_map: HashMap, } -impl KeyTreePublic { +pub type KeyTreePublic = KeyTree; +pub type KeyTreePrivate = KeyTree; + +impl KeyTree { pub fn new(seed: &SeedHolder) -> Self { let seed_fit: [u8; 64] = seed.seed.clone().try_into().unwrap(); - let root_keys = ChildKeysPublic::root(seed_fit); - let address = nssa::Address::from(&root_keys.cpk); + let root_keys = Node::root(seed_fit); + let address = root_keys.address(); let mut key_map = BTreeMap::new(); let mut addr_map = HashMap::new(); @@ -199,7 +91,7 @@ impl KeyTreePublic { let child_keys = father_keys.n_th_child(next_child_id); - let address = nssa::Address::from(&child_keys.cpk); + let address = child_keys.address(); self.key_map.insert(next_cci.clone(), child_keys); self.addr_map.insert(address, next_cci); @@ -207,7 +99,7 @@ impl KeyTreePublic { Some(address) } - pub fn get_pub_keys(&self, addr: nssa::Address) -> Option<&ChildKeysPublic> { + pub fn get_pub_keys(&self, addr: nssa::Address) -> Option<&Node> { self.addr_map .get(&addr) .and_then(|chain_id| self.key_map.get(chain_id)) @@ -216,95 +108,12 @@ impl KeyTreePublic { #[cfg(test)] mod tests { + use std::str::FromStr; + use nssa::Address; use super::*; - #[test] - fn test_chain_id_root_correct() { - let chain_id = ChainIndex::root(); - let chain_id_2 = ChainIndex::from_str("").unwrap(); - - assert_eq!(chain_id, chain_id_2); - } - - #[test] - fn test_chain_id_deser_correct() { - let chain_id = ChainIndex::from_str("01010000").unwrap(); - - assert_eq!(chain_id.chain(), &[257]); - } - - #[test] - fn test_chain_id_next_in_line_correct() { - let chain_id = ChainIndex::from_str("01010000").unwrap(); - let next_in_line = chain_id.next_in_line(); - - assert_eq!(next_in_line, ChainIndex::from_str("02010000").unwrap()); - } - - #[test] - fn test_chain_id_child_correct() { - let chain_id = ChainIndex::from_str("01010000").unwrap(); - let child = chain_id.n_th_child(3); - - assert_eq!(child, ChainIndex::from_str("0101000003000000").unwrap()); - } - - #[test] - fn test_keys_deterministic_generation() { - let root_keys = ChildKeysPublic::root([42; 64]); - let child_keys = root_keys.n_th_child(5); - - assert_eq!(root_keys.cci, None); - assert_eq!(child_keys.cci, Some(5)); - - assert_eq!( - root_keys.ccc, - [ - 61, 30, 91, 26, 133, 91, 236, 192, 231, 53, 186, 139, 11, 221, 202, 11, 178, 215, - 254, 103, 191, 60, 117, 112, 1, 226, 31, 156, 83, 104, 150, 224 - ] - ); - assert_eq!( - child_keys.ccc, - [ - 67, 26, 102, 68, 189, 155, 102, 80, 199, 188, 112, 142, 207, 157, 36, 210, 48, 224, - 35, 6, 112, 180, 11, 190, 135, 218, 9, 14, 84, 231, 58, 98 - ] - ); - - assert_eq!( - root_keys.csk.value(), - &[ - 241, 82, 246, 237, 62, 130, 116, 47, 189, 112, 99, 67, 178, 40, 115, 245, 141, 193, - 77, 164, 243, 76, 222, 64, 50, 146, 23, 145, 91, 164, 92, 116 - ] - ); - assert_eq!( - child_keys.csk.value(), - &[ - 11, 151, 27, 212, 167, 26, 77, 234, 103, 145, 53, 191, 184, 25, 240, 191, 156, 25, - 60, 144, 65, 22, 193, 163, 246, 227, 212, 81, 49, 170, 33, 158 - ] - ); - - assert_eq!( - root_keys.cpk.value(), - &[ - 220, 170, 95, 177, 121, 37, 86, 166, 56, 238, 232, 72, 21, 106, 107, 217, 158, 74, - 133, 91, 143, 244, 155, 15, 2, 230, 223, 169, 13, 20, 163, 138 - ] - ); - assert_eq!( - child_keys.cpk.value(), - &[ - 152, 249, 236, 111, 132, 96, 184, 122, 21, 179, 240, 15, 234, 155, 164, 144, 108, - 110, 120, 74, 176, 147, 196, 168, 243, 186, 203, 79, 97, 17, 194, 52 - ] - ); - } - fn seed_holder_for_tests() -> SeedHolder { SeedHolder { seed: [42; 64].to_vec(), diff --git a/key_protocol/src/key_management/key_tree/traits.rs b/key_protocol/src/key_management/key_tree/traits.rs new file mode 100644 index 0000000..662481a --- /dev/null +++ b/key_protocol/src/key_management/key_tree/traits.rs @@ -0,0 +1,11 @@ +pub trait KeyNode { + fn root(seed: [u8; 64]) -> Self; + + fn n_th_child(&self, cci: u32) -> Self; + + fn chain_code(&self) -> &[u8; 32]; + + fn child_index(&self) -> &Option; + + fn address(&self) -> nssa::Address; +} diff --git a/key_protocol/src/key_management/secret_holders.rs b/key_protocol/src/key_management/secret_holders.rs index f05a641..ee7aced 100644 --- a/key_protocol/src/key_management/secret_holders.rs +++ b/key_protocol/src/key_management/secret_holders.rs @@ -45,8 +45,8 @@ impl SeedHolder { } pub fn new_mnemonic(passphrase: String) -> Self { - let mut enthopy_bytes: [u8; 32] = [0; 32]; - OsRng.fill_bytes(&mut enthopy_bytes); + //Enthropy bytes must be deterministic as well + let enthopy_bytes: [u8; 32] = [0; 32]; let mnemonic = Mnemonic::from_entropy(&enthopy_bytes).unwrap(); let seed_wide = mnemonic.to_seed(passphrase); diff --git a/key_protocol/src/key_protocol_core/mod.rs b/key_protocol/src/key_protocol_core/mod.rs index 33a007a..6731da8 100644 --- a/key_protocol/src/key_protocol_core/mod.rs +++ b/key_protocol/src/key_protocol_core/mod.rs @@ -4,18 +4,26 @@ use anyhow::Result; use k256::AffinePoint; use serde::{Deserialize, Serialize}; -use crate::key_management::KeyChain; +use crate::key_management::{ + KeyChain, + key_tree::{KeyTreePrivate, KeyTreePublic, chain_index::ChainIndex}, +}; pub type PublicKey = AffinePoint; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct NSSAUserData { - ///Map for all user public accounts - pub pub_account_signing_keys: HashMap, - ///Map for all user private accounts - pub user_private_accounts: HashMap, + ///Default public accounts + pub default_pub_account_signing_keys: HashMap, + ///Default private accounts + pub default_user_private_accounts: + HashMap, ///Mnemonic passphrase pub password: String, + /// Tree of public keys + pub public_key_tree: KeyTreePublic, + /// Tree of private keys + pub private_key_tree: KeyTreePrivate, } impl NSSAUserData { @@ -97,13 +105,13 @@ impl NSSAUserData { /// Generated new private key for public transaction signatures /// /// Returns the address of new account - pub fn generate_new_public_transaction_private_key(&mut self) -> nssa::Address { - let private_key = nssa::PrivateKey::new_os_random(); - let address = nssa::Address::from(&nssa::PublicKey::new_from_private_key(&private_key)); - - self.pub_account_signing_keys.insert(address, private_key); - - address + pub fn generate_new_public_transaction_private_key( + &mut self, + parent_cci: ChainIndex, + ) -> nssa::Address { + self.public_key_tree + .generate_new_pub_keys(parent_cci) + .unwrap() } /// Returns the signing key for public transaction signatures @@ -111,7 +119,7 @@ impl NSSAUserData { &self, address: &nssa::Address, ) -> Option<&nssa::PrivateKey> { - self.pub_account_signing_keys.get(address) + self.public_key_tree.get_pub_keys(address) } /// Generated new private key for privacy preserving transactions diff --git a/nssa/src/signature/public_key.rs b/nssa/src/signature/public_key.rs index dbd7d64..095025d 100644 --- a/nssa/src/signature/public_key.rs +++ b/nssa/src/signature/public_key.rs @@ -1,10 +1,11 @@ use nssa_core::address::Address; +use serde::{Deserialize, Serialize}; use crate::{PrivateKey, error::NssaError}; use sha2::{Digest, Sha256}; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct PublicKey([u8; 32]); impl PublicKey {