diff options
Diffstat (limited to 'src/std_identity.rs')
| -rw-r--r-- | src/std_identity.rs | 260 |
1 files changed, 170 insertions, 90 deletions
diff --git a/src/std_identity.rs b/src/std_identity.rs index fdc8dff..80c1651 100644 --- a/src/std_identity.rs +++ b/src/std_identity.rs @@ -1,14 +1,18 @@ -use std::{collections::{HashMap, HashSet}, rc::Rc, str::FromStr}; +use crate::crypto::{PrivateKey, PublicKey, SharedSecret}; use bytes::Bytes; use log::warn; -use crate::{crypto::{PrivateKey, PublicKey, SharedSecret}}; +use std::{ + collections::{HashMap, HashSet}, + rc::Rc, + str::FromStr, +}; use serde::{Deserialize, de}; #[derive(PartialEq, Clone, Deserialize, Debug)] /// The Identity structure contains the information to decrypt /// incoming messages and sign and encrypt outgoing messages. -/// +/// /// It has the necessary cryptographic material needed to appear /// as this identity when creating messages. pub struct Identity { @@ -34,14 +38,14 @@ pub struct Identity { /// used because there are many many hash collisions /// when using just the 1-byte hash prefix. #[serde(skip)] - pub secrets: HashSet<(Rc<String>, SharedSecret)> + pub secrets: HashSet<(Rc<String>, SharedSecret)>, } #[derive(PartialEq, Clone, Deserialize, Debug)] /// The Contact structure contains the information needed /// to decrypt messages from a remote user intended for /// either an identity or a channel. -/// +/// /// It's cryptographic material is also needed to uniquely /// identify the origin of a message. Most source values /// are only one byte, so that information just limits the @@ -53,7 +57,7 @@ pub struct Contact { /// The provided public key of the remote contact #[serde(deserialize_with = "deserialize_public_key")] - pub public_key: PublicKey + pub public_key: PublicKey, } #[derive(PartialEq, Clone, Deserialize, Debug)] @@ -68,7 +72,7 @@ pub struct Group { /// The group's shared secret #[serde(deserialize_with = "deserialize_secret")] - pub secret: SharedSecret + pub secret: SharedSecret, } #[derive(PartialEq, Clone, Deserialize, Debug)] @@ -87,7 +91,13 @@ impl Keystore { } } - pub fn decrypt_and_id_p2p(&self, _source: u8, _dest: u8, mac: u16, data: &Bytes) -> Option<(Bytes, Rc<String>, Rc<String>)> { + pub fn decrypt_and_id_p2p( + &self, + _source: u8, + _dest: u8, + mac: u16, + data: &Bytes, + ) -> Option<(Bytes, Rc<String>, Rc<String>)> { // Just brute-force all the secrets until one matches... for identity in self.identities.iter() { for secret in identity.1.secrets.iter() { @@ -100,7 +110,12 @@ impl Keystore { None } - pub fn decrypt_and_id_group(&self, _group_hash_prefix: u8, mac: u16, data: &Bytes) -> Option<(Bytes, u32)> { + pub fn decrypt_and_id_group( + &self, + _group_hash_prefix: u8, + mac: u16, + data: &Bytes, + ) -> Option<(Bytes, u32)> { for group in self.groups.iter() { let result = group.1.secret.mac_then_decrypt(mac, data); if let Some(result) = result { @@ -111,7 +126,13 @@ impl Keystore { None } - pub fn decrypt_anon(&self, _dest: u8, pub_key: &PublicKey, mac: u16, data: &Bytes) -> Option<(Bytes, Rc<String>)> { + pub fn decrypt_anon( + &self, + _dest: u8, + pub_key: &PublicKey, + mac: u16, + data: &Bytes, + ) -> Option<(Bytes, Rc<String>)> { // For each identity, create a shared secret against the provided public key and check it. for identity in self.identities.iter() { let secret = identity.1.private_key.create_secret(pub_key); @@ -136,7 +157,7 @@ impl KeystoreInput { let mut retval = Keystore { identities: HashMap::new(), contacts: HashMap::new(), - groups: HashMap::new() + groups: HashMap::new(), }; // Iterate through the input keystore file @@ -152,15 +173,18 @@ impl KeystoreInput { for name in contact_names { if let Some(key_string) = self.contacts.get(name) { match PublicKey::from_str(&key_string) { - Ok(pub_key) => { - contacts.push(Contact { - name: Rc::new(name.to_string()), - public_key: pub_key - }); - }, - Err(e) => { - warn!("Unable to add contact named \"{}\" because there was a problem with the public key: {}", name, e); - } + Ok(pub_key) => { + contacts.push(Contact { + name: Rc::new(name.to_string()), + public_key: pub_key, + }); + } + Err(e) => { + warn!( + "Unable to add contact named \"{}\" because there was a problem with the public key: {}", + name, e + ); + } } } } @@ -177,18 +201,21 @@ impl KeystoreInput { name: Rc::new(name.to_string()), private_key, public_key, - secrets: HashSet::new() + secrets: HashSet::new(), }; - i.secrets = contacts.iter().map(|c| { - (c.name.clone(), i.private_key.create_secret(&c.public_key)) - }).collect(); - + i.secrets = contacts + .iter() + .map(|c| (c.name.clone(), i.private_key.create_secret(&c.public_key))) + .collect(); identities.push((i.name.clone(), i)); - }, + } Err(e) => { - warn!("Unable to add identity named \"{}\" because there was a problem with the private key: {}", name, e); + warn!( + "Unable to add identity named \"{}\" because there was a problem with the private key: {}", + name, e + ); } } } @@ -197,9 +224,7 @@ impl KeystoreInput { retval.identities = HashMap::from_iter(identities); // Create a hash of contacts - let contacts = contacts.into_iter().map(|c| { - (c.name.clone(), c) - }); + let contacts = contacts.into_iter().map(|c| (c.name.clone(), c)); retval.contacts = HashMap::from_iter(contacts); @@ -218,136 +243,179 @@ impl KeystoreInput { }); retval.groups = HashMap::from_iter(groups); - + retval } } fn deserialize_private_key<'de, D>(deserializer: D) -> Result<PrivateKey, D::Error> - where D: de::Deserializer<'de> { - +where + D: de::Deserializer<'de>, +{ + use crate::crypto::PrivateKey; use std::str::FromStr; - use crate::crypto::{PrivateKey}; let s: String = de::Deserialize::deserialize(deserializer)?; match PrivateKey::from_str(&s) { Ok(key) => Ok(key), - Err(e) => { - Err(de::Error::custom(format!("{}", e))) - } + Err(e) => Err(de::Error::custom(format!("{}", e))), } } fn deserialize_public_key<'de, D>(deserializer: D) -> Result<PublicKey, D::Error> - where D: de::Deserializer<'de> { - - use hex::decode; +where + D: de::Deserializer<'de>, +{ use crate::crypto::{MeshcoreCryptoError, PublicKey}; + use hex::decode; let s: String = de::Deserialize::deserialize(deserializer)?; match decode(s) { Err(hex::FromHexError::InvalidHexCharacter { c, index }) => { - Err(de::Error::custom(format!("Invalid hex character {} at {} when decoding Public Key.", c, index))) - }, - Err(hex::FromHexError::OddLength) => { - Err(de::Error::custom(format!("Odd number of characters when decoding Public Key."))) - }, - Err(hex::FromHexError::InvalidStringLength) => { - Err(de::Error::custom(format!("Invalid hex string length when decoding Public Key."))) + Err(de::Error::custom(format!( + "Invalid hex character {} at {} when decoding Public Key.", + c, index + ))) } + Err(hex::FromHexError::OddLength) => Err(de::Error::custom(format!( + "Odd number of characters when decoding Public Key." + ))), + Err(hex::FromHexError::InvalidStringLength) => Err(de::Error::custom(format!( + "Invalid hex string length when decoding Public Key." + ))), Ok(hex) => { let key = PublicKey::try_from(hex.as_slice()); match key { Ok(key) => Ok(key), - Err(MeshcoreCryptoError::KeyCreationError) => { - Err(de::Error::custom(format!("Unable to decompress public key points"))) - } - Err(_) => { - Err(de::Error::custom(format!("Invalid hex string length when decoding Public Key."))) - } + Err(MeshcoreCryptoError::KeyCreationError) => Err(de::Error::custom(format!( + "Unable to decompress public key points" + ))), + Err(_) => Err(de::Error::custom(format!( + "Invalid hex string length when decoding Public Key." + ))), } } } } fn deserialize_secret<'de, D>(deserializer: D) -> Result<SharedSecret, D::Error> - where D: de::Deserializer<'de> { - - use std::str::FromStr; +where + D: de::Deserializer<'de>, +{ use crate::crypto::SharedSecret; + use std::str::FromStr; let s: String = de::Deserialize::deserialize(deserializer)?; match SharedSecret::from_str(&s) { Ok(secret) => Ok(secret), - Err(e) => { - Err(de::Error::custom(format!("{}", e))) - } + Err(e) => Err(de::Error::custom(format!("{}", e))), } } // Tests for std operations #[cfg(test)] mod tests { + use hex::decode; + use log::LevelFilter; + use serde::de::IntoDeserializer; + use serde::de::value::{Error as ValueError, StrDeserializer}; use std::io; use std::str::FromStr; use std::sync::mpsc::{Sender, channel}; use std::vec; - use hex::decode; - use log::{LevelFilter}; - use serde::de::IntoDeserializer; - use serde::de::value::{StrDeserializer, Error as ValueError}; - use crate::std_identity::KeystoreInput; - use crate::crypto::*; use super::*; + use crate::crypto::*; + use crate::std_identity::KeystoreInput; #[test] fn secret_deserializer() { - let deserializer: StrDeserializer<ValueError> = "eb50a1bcb3e4e5d7bf69a57c9dada211".into_deserializer(); + let deserializer: StrDeserializer<ValueError> = + "eb50a1bcb3e4e5d7bf69a57c9dada211".into_deserializer(); let result = deserialize_secret(deserializer); match result { - Ok(result) => assert_eq!(result, SharedSecret::from_str("eb50a1bcb3e4e5d7bf69a57c9dada211").unwrap()), + Ok(result) => assert_eq!( + result, + SharedSecret::from_str("eb50a1bcb3e4e5d7bf69a57c9dada211").unwrap() + ), Err(err) => assert!(false, "Shouldn't have had an error, but got one: {}", err), } // Test failure conditions - let deserializer: StrDeserializer<ValueError> = "eb50a1bcb3e4e5d7bf69a57c9dada21".into_deserializer(); + let deserializer: StrDeserializer<ValueError> = + "eb50a1bcb3e4e5d7bf69a57c9dada21".into_deserializer(); let result = deserialize_secret(deserializer); let error = result.unwrap_err(); - assert_eq!(error.to_string(), "Try From Slice Error", "Unexpected error response: {}", error.to_string()); + assert_eq!( + error.to_string(), + "Try From Slice Error", + "Unexpected error response: {}", + error.to_string() + ); } #[test] fn public_key_deserializer() { - let deserializer: StrDeserializer<ValueError> = "34569df1f9661916901669666fb8025eccb9ddb0499cddad4c164fec219c8b8f".into_deserializer(); + let deserializer: StrDeserializer<ValueError> = + "34569df1f9661916901669666fb8025eccb9ddb0499cddad4c164fec219c8b8f".into_deserializer(); let result = deserialize_public_key(deserializer); match result { - Ok(result) => assert_eq!(result, PublicKey::from_str("34569df1f9661916901669666fb8025eccb9ddb0499cddad4c164fec219c8b8f").unwrap()), + Ok(result) => assert_eq!( + result, + PublicKey::from_str( + "34569df1f9661916901669666fb8025eccb9ddb0499cddad4c164fec219c8b8f" + ) + .unwrap() + ), Err(err) => assert!(false, "Shouldn't have had an error, but got one: {}", err), } // Test failure conditions - let deserializer: StrDeserializer<ValueError> = "34569df1f9661916901669666fb8025eccb9ddb0499cddad4c164fec219".into_deserializer(); + let deserializer: StrDeserializer<ValueError> = + "34569df1f9661916901669666fb8025eccb9ddb0499cddad4c164fec219".into_deserializer(); let result = deserialize_public_key(deserializer); let error = result.unwrap_err(); - assert_eq!(error.to_string(), "Odd number of characters when decoding Public Key.", "Unexpected error response: {}", error.to_string()); + assert_eq!( + error.to_string(), + "Odd number of characters when decoding Public Key.", + "Unexpected error response: {}", + error.to_string() + ); - let deserializer: StrDeserializer<ValueError> = "34569df1f9661916901669666fb8025eccb9ddb0499cddad4c164fec21".into_deserializer(); + let deserializer: StrDeserializer<ValueError> = + "34569df1f9661916901669666fb8025eccb9ddb0499cddad4c164fec21".into_deserializer(); let result = deserialize_public_key(deserializer); let error = result.unwrap_err(); - assert_eq!(error.to_string(), "Invalid hex string length when decoding Public Key.", "Unexpected error response: {}", error.to_string()); + assert_eq!( + error.to_string(), + "Invalid hex string length when decoding Public Key.", + "Unexpected error response: {}", + error.to_string() + ); - let deserializer: StrDeserializer<ValueError> = "34569df1f9661916901669666fb8025eccb9ddb0499cddad4b164f4c219a8b8f".into_deserializer(); + let deserializer: StrDeserializer<ValueError> = + "34569df1f9661916901669666fb8025eccb9ddb0499cddad4b164f4c219a8b8f".into_deserializer(); let result = deserialize_public_key(deserializer); let error = result.unwrap_err(); - assert_eq!(error.to_string(), "Unable to decompress public key points", "Unexpected error response: {}", error.to_string()); + assert_eq!( + error.to_string(), + "Unable to decompress public key points", + "Unexpected error response: {}", + error.to_string() + ); - let deserializer: StrDeserializer<ValueError> = "34569df1f9661916901669666fb8z25eccb9ddb0499cddad4b164f4c219a8b8f".into_deserializer(); + let deserializer: StrDeserializer<ValueError> = + "34569df1f9661916901669666fb8z25eccb9ddb0499cddad4b164f4c219a8b8f".into_deserializer(); let result = deserialize_public_key(deserializer); let error = result.unwrap_err(); - assert_eq!(error.to_string(), "Invalid hex character z at 28 when decoding Public Key.", "Unexpected error response: {}", error.to_string()); + assert_eq!( + error.to_string(), + "Invalid hex character z at 28 when decoding Public Key.", + "Unexpected error response: {}", + error.to_string() + ); } #[test] @@ -363,12 +431,22 @@ mod tests { let deserializer: StrDeserializer<ValueError> = "4885CF25975EA09742EF76DA587D0957E74EE02AAA34A001458E207E63CF7E6C4940C8C42C335862C71CC2F139633057D1FEE5687B172B27E1E0302A1D480E0".into_deserializer(); let result = deserialize_private_key(deserializer); let error = result.unwrap_err(); - assert_eq!(error.to_string(), "Hex Decode Error", "Unexpected error response: {}", error.to_string()); + assert_eq!( + error.to_string(), + "Hex Decode Error", + "Unexpected error response: {}", + error.to_string() + ); let deserializer: StrDeserializer<ValueError> = "4885CF25975EA09742EF76DA587D0957E74EE02AAA34A001458E207E63CF7E6C4940C8C42C335862C71CC2F139633057D1FEE5687B172B27E1E0302A1D480E".into_deserializer(); let result = deserialize_private_key(deserializer); let error = result.unwrap_err(); - assert_eq!(error.to_string(), "Try From Slice Error", "Unexpected error response: {}", error.to_string()); + assert_eq!( + error.to_string(), + "Try From Slice Error", + "Unexpected error response: {}", + error.to_string() + ); } #[test] @@ -394,7 +472,6 @@ mod tests { ]) }; assert_eq!(lhs, rhs); - } // This struct is used as an adaptor, it implements io::Write and forwards the buffer to a mpsc::Sender @@ -432,7 +509,9 @@ mod tests { let _ = pretty_env_logger::env_logger::builder() .is_test(true) .filter_level(LevelFilter::max()) - .target(pretty_env_logger::env_logger::Target::Pipe(Box::new(WriteAdapter { sender: rx }))) + .target(pretty_env_logger::env_logger::Target::Pipe(Box::new( + WriteAdapter { sender: rx }, + ))) .try_init(); // Test failure conditions @@ -459,11 +538,12 @@ mod tests { .zip(expect.into_iter()) .for_each(|(got, expect)| { println!("{}", &got); - assert!(got.contains(expect), "Got log line: \"{}\" and didn't find \"{}\" within it as expected.", got, expect); - } - ); - + assert!( + got.contains(expect), + "Got log line: \"{}\" and didn't find \"{}\" within it as expected.", + got, + expect + ); + }); } - - -}
\ No newline at end of file +} |
