refactor
This commit is contained in:
		| @@ -91,7 +91,7 @@ impl Crypto { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub async fn init(&self) -> Result<(), String> { | ||||
|     pub async fn init(&self) -> EyreResult<()> { | ||||
|         trace!("Crypto::init"); | ||||
|  | ||||
|         // make local copy of node id for easy access | ||||
| @@ -136,7 +136,7 @@ impl Crypto { | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     pub async fn flush(&self) -> Result<(), String> { | ||||
|     pub async fn flush(&self) -> EyreResult<()> { | ||||
|         //trace!("Crypto::flush"); | ||||
|         let (table_store, cache_bytes) = { | ||||
|             let inner = self.inner.lock(); | ||||
| @@ -166,23 +166,27 @@ impl Crypto { | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     fn ed25519_to_x25519_pk(key: &ed::PublicKey) -> Result<xd::PublicKey, String> { | ||||
|     fn ed25519_to_x25519_pk(key: &ed::PublicKey) -> Result<xd::PublicKey, VeilidAPIError> { | ||||
|         let bytes = key.to_bytes(); | ||||
|         let compressed = cd::edwards::CompressedEdwardsY(bytes); | ||||
|         let point = compressed | ||||
|             .decompress() | ||||
|             .ok_or_else(fn_string!("ed25519_to_x25519_pk failed"))?; | ||||
|             .ok_or_else(|| VeilidAPIError::internal("ed25519_to_x25519_pk failed"))?; | ||||
|         let mp = point.to_montgomery(); | ||||
|         Ok(xd::PublicKey::from(mp.to_bytes())) | ||||
|     } | ||||
|     fn ed25519_to_x25519_sk(key: &ed::SecretKey) -> Result<xd::StaticSecret, String> { | ||||
|     fn ed25519_to_x25519_sk(key: &ed::SecretKey) -> Result<xd::StaticSecret, VeilidAPIError> { | ||||
|         let exp = ed::ExpandedSecretKey::from(key); | ||||
|         let bytes: [u8; ed::EXPANDED_SECRET_KEY_LENGTH] = exp.to_bytes(); | ||||
|         let lowbytes: [u8; 32] = bytes[0..32].try_into().map_err(map_to_string)?; | ||||
|         let lowbytes: [u8; 32] = bytes[0..32].try_into().map_err(VeilidAPIError::internal)?; | ||||
|         Ok(xd::StaticSecret::from(lowbytes)) | ||||
|     } | ||||
|  | ||||
|     pub fn cached_dh(&self, key: &DHTKey, secret: &DHTKeySecret) -> Result<SharedSecret, String> { | ||||
|     pub fn cached_dh( | ||||
|         &self, | ||||
|         key: &DHTKey, | ||||
|         secret: &DHTKeySecret, | ||||
|     ) -> Result<SharedSecret, VeilidAPIError> { | ||||
|         Ok( | ||||
|             match self.inner.lock().dh_cache.entry(DHCacheKey { | ||||
|                 key: *key, | ||||
| @@ -201,12 +205,12 @@ impl Crypto { | ||||
|     /////////// | ||||
|     // These are safe to use regardless of initialization status | ||||
|  | ||||
|     pub fn compute_dh(key: &DHTKey, secret: &DHTKeySecret) -> Result<SharedSecret, String> { | ||||
|     pub fn compute_dh(key: &DHTKey, secret: &DHTKeySecret) -> Result<SharedSecret, VeilidAPIError> { | ||||
|         assert!(key.valid); | ||||
|         assert!(secret.valid); | ||||
|         let pk_ed = ed::PublicKey::from_bytes(&key.bytes).map_err(map_to_string)?; | ||||
|         let pk_ed = ed::PublicKey::from_bytes(&key.bytes).map_err(VeilidAPIError::internal)?; | ||||
|         let pk_xd = Self::ed25519_to_x25519_pk(&pk_ed)?; | ||||
|         let sk_ed = ed::SecretKey::from_bytes(&secret.bytes).map_err(map_to_string)?; | ||||
|         let sk_ed = ed::SecretKey::from_bytes(&secret.bytes).map_err(VeilidAPIError::internal)?; | ||||
|         let sk_xd = Self::ed25519_to_x25519_sk(&sk_ed)?; | ||||
|         Ok(sk_xd.diffie_hellman(&pk_xd).to_bytes()) | ||||
|     } | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| use super::crypto::*; | ||||
| use super::key::*; | ||||
| use crate::xx::*; | ||||
| use crate::*; | ||||
| use core::convert::TryInto; | ||||
|  | ||||
| // #[repr(C, packed)] | ||||
| @@ -76,89 +77,103 @@ impl Envelope { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn from_signed_data(data: &[u8]) -> Result<Envelope, ()> { | ||||
|     pub fn from_signed_data(data: &[u8]) -> Result<Envelope, VeilidAPIError> { | ||||
|         // Ensure we are at least the length of the envelope | ||||
|         // Silent drop here, as we use zero length packets as part of the protocol for hole punching | ||||
|         if data.len() < MIN_ENVELOPE_SIZE { | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::generic("envelope data too small")); | ||||
|         } | ||||
|  | ||||
|         // Verify magic number | ||||
|         let magic: [u8; 4] = data[0x00..0x04].try_into().map_err(drop)?; | ||||
|         let magic: [u8; 4] = data[0x00..0x04] | ||||
|             .try_into() | ||||
|             .map_err(VeilidAPIError::internal)?; | ||||
|         if magic != *ENVELOPE_MAGIC { | ||||
|             trace!("bad magic number: len={:?}", magic); | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::generic("bad magic number")); | ||||
|         } | ||||
|  | ||||
|         // Check version | ||||
|         let version = data[0x04]; | ||||
|         if version > MAX_VERSION || version < MIN_VERSION { | ||||
|             trace!("unsupported protocol version: version={}", version); | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::parse_error( | ||||
|                 "unsupported protocol version", | ||||
|                 version, | ||||
|             )); | ||||
|         } | ||||
|  | ||||
|         // Get min version | ||||
|         let min_version = data[0x05]; | ||||
|         if min_version > version { | ||||
|             trace!( | ||||
|                 "invalid version information in envelope: min_version={}, version={}", | ||||
|                 min_version, | ||||
|                 version, | ||||
|             ); | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::parse_error("version too low", version)); | ||||
|         } | ||||
|  | ||||
|         // Get max version | ||||
|         let max_version = data[0x06]; | ||||
|         if version > max_version || min_version > max_version { | ||||
|             trace!( | ||||
|                 "invalid version information in envelope: min_version={}, version={}, max_version={}", | ||||
|                 min_version, | ||||
|                 version, | ||||
|                 max_version | ||||
|             ); | ||||
|             return Err(()); | ||||
|         if version > max_version { | ||||
|             return Err(VeilidAPIError::parse_error("version too high", version)); | ||||
|         } | ||||
|         if min_version > max_version { | ||||
|             return Err(VeilidAPIError::generic("version information invalid")); | ||||
|         } | ||||
|  | ||||
|         // Get size and ensure it matches the size of the envelope and is less than the maximum message size | ||||
|         let size: u16 = u16::from_le_bytes(data[0x08..0x0A].try_into().map_err(drop)?); | ||||
|         let size: u16 = u16::from_le_bytes( | ||||
|             data[0x08..0x0A] | ||||
|                 .try_into() | ||||
|                 .map_err(VeilidAPIError::internal)?, | ||||
|         ); | ||||
|         if (size as usize) > MAX_ENVELOPE_SIZE { | ||||
|             trace!("envelope size is too large: size={}", size); | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::parse_error("envelope too large", size)); | ||||
|         } | ||||
|         if (size as usize) != data.len() { | ||||
|             trace!( | ||||
|                 "size doesn't match envelope size: size={} data.len()={}", | ||||
|                 size, | ||||
|                 data.len() | ||||
|             ); | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::parse_error( | ||||
|                 "size doesn't match envelope size", | ||||
|                 format!( | ||||
|                     "size doesn't match envelope size: size={} data.len()={}", | ||||
|                     size, | ||||
|                     data.len() | ||||
|                 ), | ||||
|             )); | ||||
|         } | ||||
|  | ||||
|         // Get the timestamp | ||||
|         let timestamp: u64 = u64::from_le_bytes(data[0x0A..0x12].try_into().map_err(drop)?); | ||||
|         let timestamp: u64 = u64::from_le_bytes( | ||||
|             data[0x0A..0x12] | ||||
|                 .try_into() | ||||
|                 .map_err(VeilidAPIError::internal)?, | ||||
|         ); | ||||
|  | ||||
|         // Get nonce and sender node id | ||||
|         let nonce: EnvelopeNonce = data[0x12..0x2A].try_into().map_err(drop)?; | ||||
|         let sender_id_slice: [u8; 32] = data[0x2A..0x4A].try_into().map_err(drop)?; | ||||
|         let recipient_id_slice: [u8; 32] = data[0x4A..0x6A].try_into().map_err(drop)?; | ||||
|         let nonce: EnvelopeNonce = data[0x12..0x2A] | ||||
|             .try_into() | ||||
|             .map_err(VeilidAPIError::internal)?; | ||||
|         let sender_id_slice: [u8; 32] = data[0x2A..0x4A] | ||||
|             .try_into() | ||||
|             .map_err(VeilidAPIError::internal)?; | ||||
|         let recipient_id_slice: [u8; 32] = data[0x4A..0x6A] | ||||
|             .try_into() | ||||
|             .map_err(VeilidAPIError::internal)?; | ||||
|         let sender_id = DHTKey::new(sender_id_slice); | ||||
|         let recipient_id = DHTKey::new(recipient_id_slice); | ||||
|  | ||||
|         // Ensure sender_id and recipient_id are not the same | ||||
|         if sender_id == recipient_id { | ||||
|             trace!( | ||||
|                 "sender_id should not be same as recipient_id: {}", | ||||
|                 recipient_id.encode() | ||||
|             ); | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::parse_error( | ||||
|                 "sender_id should not be same as recipient_id", | ||||
|                 recipient_id.encode(), | ||||
|             )); | ||||
|         } | ||||
|  | ||||
|         // Get signature | ||||
|         let signature = DHTSignature::new(data[(data.len() - 64)..].try_into().map_err(drop)?); | ||||
|         let signature = DHTSignature::new( | ||||
|             data[(data.len() - 64)..] | ||||
|                 .try_into() | ||||
|                 .map_err(VeilidAPIError::internal)?, | ||||
|         ); | ||||
|  | ||||
|         // Validate signature | ||||
|         verify(&sender_id, &data[0..(data.len() - 64)], &signature).map_err(drop)?; | ||||
|         verify(&sender_id, &data[0..(data.len() - 64)], &signature) | ||||
|             .map_err(VeilidAPIError::internal)?; | ||||
|  | ||||
|         // Return envelope | ||||
|         Ok(Self { | ||||
| @@ -177,7 +192,7 @@ impl Envelope { | ||||
|         crypto: Crypto, | ||||
|         data: &[u8], | ||||
|         node_id_secret: &DHTKeySecret, | ||||
|     ) -> Result<Vec<u8>, String> { | ||||
|     ) -> Result<Vec<u8>, VeilidAPIError> { | ||||
|         // Get DH secret | ||||
|         let dh_secret = crypto.cached_dh(&self.sender_id, node_id_secret)?; | ||||
|  | ||||
| @@ -192,20 +207,23 @@ impl Envelope { | ||||
|         crypto: Crypto, | ||||
|         body: &[u8], | ||||
|         node_id_secret: &DHTKeySecret, | ||||
|     ) -> Result<Vec<u8>, ()> { | ||||
|     ) -> Result<Vec<u8>, VeilidAPIError> { | ||||
|         // Ensure sender node id is valid | ||||
|         if !self.sender_id.valid { | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::generic("sender id is invalid")); | ||||
|         } | ||||
|         // Ensure recipient node id is valid | ||||
|         if !self.recipient_id.valid { | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::generic("recipient id is invalid")); | ||||
|         } | ||||
|  | ||||
|         // Ensure body isn't too long | ||||
|         let envelope_size: usize = body.len() + MIN_ENVELOPE_SIZE; | ||||
|         if envelope_size > MAX_ENVELOPE_SIZE { | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::parse_error( | ||||
|                 "envelope size is too large", | ||||
|                 envelope_size, | ||||
|             )); | ||||
|         } | ||||
|         let mut data = vec![0u8; envelope_size]; | ||||
|  | ||||
| @@ -229,9 +247,7 @@ impl Envelope { | ||||
|         data[0x4A..0x6A].copy_from_slice(&self.recipient_id.bytes); | ||||
|  | ||||
|         // Generate dh secret | ||||
|         let dh_secret = crypto | ||||
|             .cached_dh(&self.recipient_id, node_id_secret) | ||||
|             .map_err(drop)?; | ||||
|         let dh_secret = crypto.cached_dh(&self.recipient_id, node_id_secret)?; | ||||
|  | ||||
|         // Encrypt and authenticate message | ||||
|         let encrypted_body = Crypto::crypt_no_auth(body, &self.nonce, &dh_secret); | ||||
| @@ -246,8 +262,7 @@ impl Envelope { | ||||
|             &self.sender_id, | ||||
|             node_id_secret, | ||||
|             &data[0..(envelope_size - 64)], | ||||
|         ) | ||||
|         .map_err(drop)?; | ||||
|         )?; | ||||
|  | ||||
|         // Append the signature | ||||
|         data[(envelope_size - 64)..].copy_from_slice(&signature.bytes); | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| use super::envelope::{MAX_VERSION, MIN_VERSION}; | ||||
| use super::key::*; | ||||
| use crate::xx::*; | ||||
| use crate::*; | ||||
| use core::convert::TryInto; | ||||
| use data_encoding::BASE64URL_NOPAD; | ||||
|  | ||||
| @@ -57,10 +58,13 @@ impl Receipt { | ||||
|         nonce: ReceiptNonce, | ||||
|         sender_id: DHTKey, | ||||
|         extra_data: D, | ||||
|     ) -> Result<Self, String> { | ||||
|     ) -> Result<Self, VeilidAPIError> { | ||||
|         assert!(sender_id.valid); | ||||
|         if extra_data.as_ref().len() > MAX_EXTRA_DATA_SIZE { | ||||
|             return Err("extra data too large for receipt".to_owned()); | ||||
|             return Err(VeilidAPIError::parse_error( | ||||
|                 "extra data too large for receipt", | ||||
|                 extra_data.as_ref().len(), | ||||
|             )); | ||||
|         } | ||||
|         Ok(Self { | ||||
|             version, | ||||
| @@ -70,53 +74,70 @@ impl Receipt { | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub fn from_signed_data(data: &[u8]) -> Result<Receipt, ()> { | ||||
|     pub fn from_signed_data(data: &[u8]) -> Result<Receipt, VeilidAPIError> { | ||||
|         // Ensure we are at least the length of the envelope | ||||
|         if data.len() < MIN_RECEIPT_SIZE { | ||||
|             trace!("receipt too small: len={}", data.len()); | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::parse_error("receipt too small", data.len())); | ||||
|         } | ||||
|  | ||||
|         // Verify magic number | ||||
|         let magic: [u8; 4] = data[0x00..0x04].try_into().map_err(drop)?; | ||||
|         let magic: [u8; 4] = data[0x00..0x04] | ||||
|             .try_into() | ||||
|             .map_err(VeilidAPIError::internal)?; | ||||
|         if magic != *RECEIPT_MAGIC { | ||||
|             trace!("bad magic number: len={:?}", magic); | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::generic("bad magic number")); | ||||
|         } | ||||
|  | ||||
|         // Check version | ||||
|         let version = data[0x04]; | ||||
|         if version > MAX_VERSION || version < MIN_VERSION { | ||||
|             trace!("unsupported protocol version: version={}", version); | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::parse_error( | ||||
|                 "unsupported protocol version", | ||||
|                 version, | ||||
|             )); | ||||
|         } | ||||
|  | ||||
|         // Get size and ensure it matches the size of the envelope and is less than the maximum message size | ||||
|         let size: u16 = u16::from_le_bytes(data[0x06..0x08].try_into().map_err(drop)?); | ||||
|         let size: u16 = u16::from_le_bytes( | ||||
|             data[0x06..0x08] | ||||
|                 .try_into() | ||||
|                 .map_err(VeilidAPIError::internal)?, | ||||
|         ); | ||||
|         if (size as usize) > MAX_RECEIPT_SIZE { | ||||
|             trace!("receipt size is too large: size={}", size); | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::parse_error( | ||||
|                 "receipt size is too large", | ||||
|                 size, | ||||
|             )); | ||||
|         } | ||||
|         if (size as usize) != data.len() { | ||||
|             trace!( | ||||
|                 "size doesn't match receipt size: size={} data.len()={}", | ||||
|                 size, | ||||
|                 data.len() | ||||
|             ); | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::parse_error( | ||||
|                 "size doesn't match receipt size", | ||||
|                 format!("size={} data.len()={}", size, data.len()), | ||||
|             )); | ||||
|         } | ||||
|  | ||||
|         // Get sender id | ||||
|         let sender_id = DHTKey::new(data[0x20..0x40].try_into().map_err(drop)?); | ||||
|         let sender_id = DHTKey::new( | ||||
|             data[0x20..0x40] | ||||
|                 .try_into() | ||||
|                 .map_err(VeilidAPIError::internal)?, | ||||
|         ); | ||||
|  | ||||
|         // Get signature | ||||
|         let signature = DHTSignature::new(data[(data.len() - 64)..].try_into().map_err(drop)?); | ||||
|         let signature = DHTSignature::new( | ||||
|             data[(data.len() - 64)..] | ||||
|                 .try_into() | ||||
|                 .map_err(VeilidAPIError::internal)?, | ||||
|         ); | ||||
|  | ||||
|         // Validate signature | ||||
|         verify(&sender_id, &data[0..(data.len() - 64)], &signature).map_err(drop)?; | ||||
|         verify(&sender_id, &data[0..(data.len() - 64)], &signature) | ||||
|             .map_err(VeilidAPIError::generic)?; | ||||
|  | ||||
|         // Get nonce | ||||
|         let nonce: ReceiptNonce = data[0x08..0x20].try_into().map_err(drop)?; | ||||
|         let nonce: ReceiptNonce = data[0x08..0x20] | ||||
|             .try_into() | ||||
|             .map_err(VeilidAPIError::internal)?; | ||||
|  | ||||
|         // Get extra data and signature | ||||
|         let extra_data: Vec<u8> = Vec::from(&data[0x40..(data.len() - 64)]); | ||||
| @@ -130,16 +151,19 @@ impl Receipt { | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub fn to_signed_data(&self, secret: &DHTKeySecret) -> Result<Vec<u8>, ()> { | ||||
|     pub fn to_signed_data(&self, secret: &DHTKeySecret) -> Result<Vec<u8>, VeilidAPIError> { | ||||
|         // Ensure sender node id is valid | ||||
|         if !self.sender_id.valid { | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::internal("sender id is invalid")); | ||||
|         } | ||||
|  | ||||
|         // Ensure extra data isn't too long | ||||
|         let receipt_size: usize = self.extra_data.len() + MIN_RECEIPT_SIZE; | ||||
|         if receipt_size > MAX_RECEIPT_SIZE { | ||||
|             return Err(()); | ||||
|             return Err(VeilidAPIError::parse_error( | ||||
|                 "receipt too large", | ||||
|                 receipt_size, | ||||
|             )); | ||||
|         } | ||||
|         let mut data: Vec<u8> = vec![0u8; receipt_size]; | ||||
|  | ||||
| @@ -158,8 +182,8 @@ impl Receipt { | ||||
|             data[0x40..(receipt_size - 64)].copy_from_slice(self.extra_data.as_slice()); | ||||
|         } | ||||
|         // Sign the receipt | ||||
|         let signature = | ||||
|             sign(&self.sender_id, secret, &data[0..(receipt_size - 64)]).map_err(drop)?; | ||||
|         let signature = sign(&self.sender_id, secret, &data[0..(receipt_size - 64)]) | ||||
|             .map_err(VeilidAPIError::generic)?; | ||||
|         // Append the signature | ||||
|         data[(receipt_size - 64)..].copy_from_slice(&signature.bytes); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user