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