break everything

This commit is contained in:
John Smith 2023-02-07 21:44:50 -05:00
parent 9d826b27db
commit a58a87719c
61 changed files with 1278 additions and 863 deletions

View File

@ -27,13 +27,24 @@ struct Nonce24 @0xb6260db25d8d7dfc {
u2 @2 :UInt64; u2 @2 :UInt64;
} }
using NodeID = Key256; using PublicKey = Key256; # Node id / DHT key / Route id, etc
using RoutePublicKey = Key256; using Nonce = Nonce24; # One-time encryption nonce
using ValueID = Key256; using Signature = Signature512; # Signature block
using Nonce = Nonce24; using TunnelID = UInt64; # Id for tunnels
using Signature = Signature512; using CryptoKind = UInt32; # FOURCC code for cryptography type
using BlockID = Key256; using ValueSeqNum = UInt32; # sequence numbers for values
using TunnelID = UInt64; using ValueSchema = UInt32; # FOURCC code for schema (0 = freeform, SUB0 = subkey control v0)
using Subkey = UInt32; # subkey index for dht
struct TypedKey {
kind @0 :CryptoKind;
key @1 :PublicKey;
}
struct TypedSignature {
kind @0 :CryptoKind;
signature @1 :Signature;
}
# Node Dial Info # Node Dial Info
################################################################ ################################################################
@ -123,7 +134,7 @@ struct RouteHopData @0x8ce231f9d1b7adf2 {
struct RouteHop @0xf8f672d75cce0c3b { struct RouteHop @0xf8f672d75cce0c3b {
node :union { node :union {
nodeId @0 :NodeID; # node id only for established routes nodeId @0 :TypedKey; # node id only for established routes
peerInfo @1 :PeerInfo; # full peer info for this hop to establish the route peerInfo @1 :PeerInfo; # full peer info for this hop to establish the route
} }
nextHop @2 :RouteHopData; # optional: If this the end of a private route, this field will not exist nextHop @2 :RouteHopData; # optional: If this the end of a private route, this field will not exist
@ -131,7 +142,7 @@ struct RouteHop @0xf8f672d75cce0c3b {
} }
struct PrivateRoute @0x8a83fccb0851e776 { struct PrivateRoute @0x8a83fccb0851e776 {
publicKey @0 :RoutePublicKey; # private route public key (unique per private route) publicKey @0 :TypedKey; # private route public key (unique per private route)
hopCount @1 :UInt8; # Count of hops left in the private route (for timeout calculation purposes only) hopCount @1 :UInt8; # Count of hops left in the private route (for timeout calculation purposes only)
hops :union { hops :union {
firstHop @2 :RouteHop; # first hop of a private route is unencrypted (hopcount > 0) firstHop @2 :RouteHop; # first hop of a private route is unencrypted (hopcount > 0)
@ -141,7 +152,7 @@ struct PrivateRoute @0x8a83fccb0851e776 {
} }
struct SafetyRoute @0xf554734d07cb5d59 { struct SafetyRoute @0xf554734d07cb5d59 {
publicKey @0 :RoutePublicKey; # safety route public key (unique per safety route) publicKey @0 :TypedKey; # safety route public key (unique per safety route)
hopCount @1 :UInt8; # Count of hops left in the safety route (for timeout calculation purposes only) hopCount @1 :UInt8; # Count of hops left in the safety route (for timeout calculation purposes only)
hops :union { hops :union {
data @2 :RouteHopData; # safety route has more hops data @2 :RouteHopData; # safety route has more hops
@ -152,16 +163,20 @@ struct SafetyRoute @0xf554734d07cb5d59 {
# Values # Values
############################## ##############################
using ValueSeqNum = UInt32; # sequence numbers for values struct SubkeyRange {
start @0 :Subkey; # the start of a subkey range
end @1 :Subkey; # the end of a subkey range
}
struct ValueKey @0xe64b0992c21a0736 { struct ValueKey @0xe64b0992c21a0736 {
publicKey @0 :ValueID; # the location of the value publicKey @0 :TypedKey; # the location of the value
subkey @1 :Text; # the name of the subkey (or empty for the default subkey) subkey @1 :Subkey; # the index of the subkey (0 for the default subkey)
} }
struct ValueData @0xb4b7416f169f2a3d { struct ValueData @0xb4b7416f169f2a3d {
seq @0 :ValueSeqNum; # sequence number of value seq @0 :ValueSeqNum; # sequence number of value
data @1 :Data; # value or subvalue contents schema @1 :ValueSchema; # fourcc code of schema for value
data @2 :Data; # value or subvalue contents
} }
# Operations # Operations
@ -234,7 +249,7 @@ struct NodeInfo @0xe125d847e3f9f419 {
networkClass @0 :NetworkClass; # network class of this node networkClass @0 :NetworkClass; # network class of this node
outboundProtocols @1 :ProtocolTypeSet; # protocols that can go outbound outboundProtocols @1 :ProtocolTypeSet; # protocols that can go outbound
addressTypes @2 :AddressTypeSet; # address types supported addressTypes @2 :AddressTypeSet; # address types supported
minVersion @3 :UInt8; # minimum protocol version for rpc envelopeSupport @3 :UInt8; # minimum protocol version for rpc
maxVersion @4 :UInt8; # maximum protocol version for rpc maxVersion @4 :UInt8; # maximum protocol version for rpc
dialInfoDetailList @5 :List(DialInfoDetail); # inbound dial info details for this node dialInfoDetailList @5 :List(DialInfoDetail); # inbound dial info details for this node
} }
@ -242,15 +257,15 @@ struct NodeInfo @0xe125d847e3f9f419 {
struct SignedDirectNodeInfo @0xe0e7ea3e893a3dd7 { struct SignedDirectNodeInfo @0xe0e7ea3e893a3dd7 {
nodeInfo @0 :NodeInfo; # node info nodeInfo @0 :NodeInfo; # node info
timestamp @1 :UInt64; # when signed node info was generated timestamp @1 :UInt64; # when signed node info was generated
signature @2 :Signature; # signature signatures @2 :List(TypedSignature); # signatures
} }
struct SignedRelayedNodeInfo @0xb39e8428ccd87cbb { struct SignedRelayedNodeInfo @0xb39e8428ccd87cbb {
nodeInfo @0 :NodeInfo; # node info nodeInfo @0 :NodeInfo; # node info
relayId @1 :NodeID; # node id for relay relayId @1 :List(TypedKey); # node ids for relay
relayInfo @2 :SignedDirectNodeInfo; # signed node info for relay relayInfo @2 :SignedDirectNodeInfo; # signed node info for relay
timestamp @3 :UInt64; # when signed node info was generated timestamp @3 :UInt64; # when signed node info was generated
signature @4 :Signature; # signature signatures @4 :List(TypedSignature); # signatures
} }
struct SignedNodeInfo @0xd2478ce5f593406a { struct SignedNodeInfo @0xd2478ce5f593406a {
@ -261,16 +276,15 @@ struct SignedNodeInfo @0xd2478ce5f593406a {
} }
struct PeerInfo @0xfe2d722d5d3c4bcb { struct PeerInfo @0xfe2d722d5d3c4bcb {
nodeId @0 :NodeID; # node id for 'closer peer' nodeIds @0 :List(TypedKey); # node ids for 'closer peer'
signedNodeInfo @1 :SignedNodeInfo; # signed node info for 'closer peer' signedNodeInfo @1 :SignedNodeInfo; # signed node info for 'closer peer'
} }
struct RoutedOperation @0xcbcb8535b839e9dd { struct RoutedOperation @0xcbcb8535b839e9dd {
version @0 :UInt8; # crypto version in use for the data sequencing @0 :Sequencing; # sequencing preference to use to pass the message along
sequencing @1 :Sequencing; # sequencing preference to use to pass the message along signatures @1 :List(TypedSignature); # signatures from nodes that have handled the private route
signatures @2 :List(Signature); # signatures from nodes that have handled the private route nonce @2 :Nonce; # nonce Xmsg
nonce @3 :Nonce; # nonce Xmsg data @3 :Data; # operation encrypted with ENC(Xmsg,DH(PKapr,SKbsr))
data @4 :Data; # operation encrypted with ENC(Xmsg,DH(PKapr,SKbsr))
} }
struct OperationStatusQ @0x865d80cea70d884a { struct OperationStatusQ @0x865d80cea70d884a {
@ -293,7 +307,7 @@ struct OperationReturnReceipt @0xeb0fb5b5a9160eeb {
} }
struct OperationFindNodeQ @0xfdef788fe9623bcd { struct OperationFindNodeQ @0xfdef788fe9623bcd {
nodeId @0 :NodeID; # node id to locate nodeId @0 :TypedKey; # node id to locate
} }
struct OperationFindNodeA @0xa84cf2fb40c77089 { struct OperationFindNodeA @0xa84cf2fb40c77089 {
@ -301,24 +315,25 @@ struct OperationFindNodeA @0xa84cf2fb40c77089 {
} }
struct OperationRoute @0x96741859ce6ac7dd { struct OperationRoute @0x96741859ce6ac7dd {
safetyRoute @0 :SafetyRoute; # Where this should go safetyRoute @0 :SafetyRoute; # where this should go
operation @1 :RoutedOperation; # The operation to be routed operation @1 :RoutedOperation; # the operation to be routed
} }
struct OperationAppCallQ @0xade67b9f09784507 { struct OperationAppCallQ @0xade67b9f09784507 {
message @0 :Data; # Opaque request to application message @0 :Data; # opaque request to application
} }
struct OperationAppCallA @0xf7c797ac85f214b8 { struct OperationAppCallA @0xf7c797ac85f214b8 {
message @0 :Data; # Opaque response from application message @0 :Data; # opaque response from application
} }
struct OperationAppMessage @0x9baf542d81b411f5 { struct OperationAppMessage @0x9baf542d81b411f5 {
message @0 :Data; # Opaque message to application message @0 :Data; # opaque message to application
} }
struct OperationGetValueQ @0xf88a5b6da5eda5d0 { struct OperationGetValueQ @0xf88a5b6da5eda5d0 {
key @0 :ValueKey; # key for value to get publicKey @0 :TypedKey; # the location of the value
subkey @1 :Subkey; # the index of the subkey (0 for the default subkey)
} }
struct OperationGetValueA @0xd896bb46f2e0249f { struct OperationGetValueA @0xd896bb46f2e0249f {
@ -329,8 +344,9 @@ struct OperationGetValueA @0xd896bb46f2e0249f {
} }
struct OperationSetValueQ @0xbac06191ff8bdbc5 { struct OperationSetValueQ @0xbac06191ff8bdbc5 {
key @0 :ValueKey; # key for value to update publicKey @0 :TypedKey; # the location of the value
value @1 :ValueData; # value or subvalue contents (older or equal seq number gets dropped) subkey @1 :Subkey; # the index of the subkey (0 for the default subkey)
value @2 :ValueData; # value or subvalue contents (older or equal seq number gets dropped)
} }
struct OperationSetValueA @0x9378d0732dc95be2 { struct OperationSetValueA @0x9378d0732dc95be2 {
@ -341,21 +357,26 @@ struct OperationSetValueA @0x9378d0732dc95be2 {
} }
struct OperationWatchValueQ @0xf9a5a6c547b9b228 { struct OperationWatchValueQ @0xf9a5a6c547b9b228 {
key @0 :ValueKey; # key for value to watch publicKey @0 :TypedKey; # key for value to watch
subkeys @1 :List(SubkeyRange) # subkey range to watch, if empty, watch everything
expiration @2 :UInt64; # requested timestamp when this watch will expire in usec since epoch (can be return less, 0 for max)
count @3 :UInt32; # requested number of changes to watch for (0 = continuous, 1 = single shot, 2+ = counter)
} }
struct OperationWatchValueA @0xa726cab7064ba893 { struct OperationWatchValueA @0xa726cab7064ba893 {
expiration @0 :UInt64; # timestamp when this watch will expire in usec since epoch (0 if watch failed) expiration @0 :UInt64; # timestamp when this watch will expire in usec since epoch (0 if watch failed)
peers @1 :List(PeerInfo); # returned list of other nodes to ask that could propagate watches peers @2 :List(PeerInfo); # returned list of other nodes to ask that could propagate watches
} }
struct OperationValueChanged @0xd1c59ebdd8cc1bf6 { struct OperationValueChanged @0xd1c59ebdd8cc1bf6 {
key @0 :ValueKey; # key for value that changed publicKey @0 :TypedKey; # key for value that changed
value @1 :ValueData; # value or subvalue contents with sequence number subkeys @1 :List(SubkeyRange) # subkey range that changed (up to 512 ranges at a time)
count @2 :UInt32; # remaining changes left (0 means watch has expired)
value @3 :ValueData; # first value that changed (the rest can be gotten with getvalue)
} }
struct OperationSupplyBlockQ @0xadbf4c542d749971 { struct OperationSupplyBlockQ @0xadbf4c542d749971 {
blockId @0 :BlockID; # hash of the block we can supply blockId @0 :TypedKey; # hash of the block we can supply
} }
struct OperationSupplyBlockA @0xf003822e83b5c0d7 { struct OperationSupplyBlockA @0xf003822e83b5c0d7 {
@ -366,7 +387,7 @@ struct OperationSupplyBlockA @0xf003822e83b5c0d7 {
} }
struct OperationFindBlockQ @0xaf4353ff004c7156 { struct OperationFindBlockQ @0xaf4353ff004c7156 {
blockId @0 :BlockID; # hash of the block to locate blockId @0 :TypedKey; # hash of the block to locate
} }
struct OperationFindBlockA @0xc51455bc4915465d { struct OperationFindBlockA @0xc51455bc4915465d {

View File

@ -67,12 +67,6 @@ impl ServicesContext {
} }
self.protected_store = Some(protected_store.clone()); self.protected_store = Some(protected_store.clone());
// Init node id from config now that protected store is set up
if let Err(e) = self.config.init_node_id(protected_store.clone()).await {
self.shutdown().await;
return Err(e).wrap_err("init node id failed");
}
// Set up tablestore // Set up tablestore
trace!("init table store"); trace!("init table store");
let table_store = TableStore::new(self.config.clone()); let table_store = TableStore::new(self.config.clone());
@ -84,7 +78,11 @@ impl ServicesContext {
// Set up crypto // Set up crypto
trace!("init crypto"); trace!("init crypto");
let crypto = Crypto::new(self.config.clone(), table_store.clone()); let crypto = Crypto::new(
self.config.clone(),
table_store.clone(),
protected_store.clone(),
);
if let Err(e) = crypto.init().await { if let Err(e) = crypto.init().await {
self.shutdown().await; self.shutdown().await;
return Err(e); return Err(e);

View File

@ -1,4 +1,4 @@
use crate::*; use super::*;
use core::cmp::{Eq, Ord, PartialEq, PartialOrd}; use core::cmp::{Eq, Ord, PartialEq, PartialOrd};
use core::convert::{TryFrom, TryInto}; use core::convert::{TryFrom, TryInto};
@ -11,24 +11,42 @@ use rkyv::{Archive as RkyvArchive, Deserialize as RkyvDeserialize, Serialize as
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
/// Length of a DHT key in bytes /// Length of a public key in bytes
#[allow(dead_code)] #[allow(dead_code)]
pub const DHT_KEY_LENGTH: usize = 32; pub const PUBLIC_KEY_LENGTH: usize = 32;
/// Length of a DHT key in bytes after encoding to base64url /// Length of a public key in bytes after encoding to base64url
#[allow(dead_code)] #[allow(dead_code)]
pub const DHT_KEY_LENGTH_ENCODED: usize = 43; pub const PUBLIC_KEY_LENGTH_ENCODED: usize = 43;
/// Length of a DHT secret in bytes /// Length of a secret key in bytes
#[allow(dead_code)] #[allow(dead_code)]
pub const DHT_KEY_SECRET_LENGTH: usize = 32; pub const SECRET_KEY_LENGTH: usize = 32;
/// Length of a DHT secret in bytes after encoding to base64url /// Length of a secret key in bytes after encoding to base64url
#[allow(dead_code)] #[allow(dead_code)]
pub const DHT_KEY_SECRET_LENGTH_ENCODED: usize = 43; pub const SECRET_KEY_LENGTH_ENCODED: usize = 43;
/// Length of a DHT signature in bytes /// Length of a signature in bytes
#[allow(dead_code)] #[allow(dead_code)]
/// Length of a DHT signature in bytes after encoding to base64url pub const SIGNATURE_LENGTH: usize = 64;
pub const DHT_SIGNATURE_LENGTH: usize = 64; /// Length of a signature in bytes after encoding to base64url
#[allow(dead_code)] #[allow(dead_code)]
pub const DHT_SIGNATURE_LENGTH_ENCODED: usize = 86; pub const SIGNATURE_LENGTH_ENCODED: usize = 86;
/// Length of a nonce in bytes
#[allow(dead_code)]
pub const NONCE_LENGTH: usize = 24;
/// Length of a nonce in bytes after encoding to base64url
#[allow(dead_code)]
pub const NONCE_LENGTH_ENCODED: usize = 32;
/// Length of a shared secret in bytes
#[allow(dead_code)]
pub const SHARED_SECRET_LENGTH: usize = 32;
/// Length of a shared secret in bytes after encoding to base64url
#[allow(dead_code)]
pub const SHARED_SECRET_LENGTH_ENCODED: usize = 43;
//////////////////////////////////////////////////////////////////////
pub trait Encodable {
fn encode(&self) -> String;
}
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -141,14 +159,13 @@ macro_rules! byte_array_type {
None None
} }
pub fn encode(&self) -> String {
BASE64URL_NOPAD.encode(&self.bytes)
}
pub fn try_decode<S: AsRef<str>>(input: S) -> Result<Self, VeilidAPIError> { pub fn try_decode<S: AsRef<str>>(input: S) -> Result<Self, VeilidAPIError> {
let b = input.as_ref().as_bytes();
Self::try_decode_bytes(b)
}
pub fn try_decode_bytes(b: &[u8]) -> Result<Self, VeilidAPIError> {
let mut bytes = [0u8; $size]; let mut bytes = [0u8; $size];
let res = BASE64URL_NOPAD.decode_len(b.len());
let res = BASE64URL_NOPAD.decode_len(input.as_ref().len());
match res { match res {
Ok(v) => { Ok(v) => {
if v != $size { if v != $size {
@ -160,7 +177,7 @@ macro_rules! byte_array_type {
} }
} }
let res = BASE64URL_NOPAD.decode_mut(input.as_ref().as_bytes(), &mut bytes); let res = BASE64URL_NOPAD.decode_mut(b, &mut bytes);
match res { match res {
Ok(_) => Ok(Self::new(bytes)), Ok(_) => Ok(Self::new(bytes)),
Err(_) => apibail_generic!("Failed to decode"), Err(_) => apibail_generic!("Failed to decode"),
@ -168,6 +185,11 @@ macro_rules! byte_array_type {
} }
} }
impl Encodable for $name {
fn encode(&self) -> String {
BASE64URL_NOPAD.encode(&self.bytes)
}
}
impl fmt::Display for $name { impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
//write!(f, "{}", String::from(self)) //write!(f, "{}", String::from(self))
@ -224,7 +246,9 @@ macro_rules! byte_array_type {
///////////////////////////////////////// /////////////////////////////////////////
byte_array_type!(DHTKey, DHT_KEY_LENGTH); byte_array_type!(PublicKey, PUBLIC_KEY_LENGTH);
byte_array_type!(DHTKeySecret, DHT_KEY_SECRET_LENGTH); byte_array_type!(SecretKey, SECRET_KEY_LENGTH);
byte_array_type!(DHTSignature, DHT_SIGNATURE_LENGTH); byte_array_type!(Signature, SIGNATURE_LENGTH);
byte_array_type!(DHTKeyDistance, DHT_KEY_LENGTH); byte_array_type!(PublicKeyDistance, PUBLIC_KEY_LENGTH);
byte_array_type!(Nonce, NONCE_LENGTH);
byte_array_type!(SharedSecret, SHARED_SECRET_LENGTH);

View File

@ -2,14 +2,14 @@ use super::*;
pub trait CryptoSystem { pub trait CryptoSystem {
// Accessors // Accessors
fn version(&self) -> CryptoVersion; fn kind(&self) -> CryptoKind;
fn crypto(&self) -> Crypto; fn crypto(&self) -> Crypto;
// Cached Operations // Cached Operations
fn cached_dh( fn cached_dh(
&self, &self,
key: &DHTKey, key: &PublicKey,
secret: &DHTKeySecret, secret: &SecretKey,
) -> Result<SharedSecret, VeilidAPIError>; ) -> Result<SharedSecret, VeilidAPIError>;
// Generation // Generation
@ -17,40 +17,40 @@ pub trait CryptoSystem {
fn random_shared_secret(&self) -> SharedSecret; fn random_shared_secret(&self) -> SharedSecret;
fn compute_dh( fn compute_dh(
&self, &self,
key: &DHTKey, key: &PublicKey,
secret: &DHTKeySecret, secret: &SecretKey,
) -> Result<SharedSecret, VeilidAPIError>; ) -> Result<SharedSecret, VeilidAPIError>;
fn generate_keypair(&self) -> (DHTKey, DHTKeySecret); fn generate_keypair(&self) -> (PublicKey, SecretKey);
fn generate_hash(&self, data: &[u8]) -> DHTKey; fn generate_hash(&self, data: &[u8]) -> PublicKey;
fn generate_hash_reader( fn generate_hash_reader(
&self, &self,
reader: &mut dyn std::io::Read, reader: &mut dyn std::io::Read,
) -> Result<DHTKey, VeilidAPIError>; ) -> Result<PublicKey, VeilidAPIError>;
// Validation // Validation
fn validate_keypair(&self, dht_key: &DHTKey, dht_key_secret: &DHTKeySecret) -> bool; fn validate_keypair(&self, dht_key: &PublicKey, dht_key_secret: &SecretKey) -> bool;
fn validate_hash(&self, data: &[u8], dht_key: &DHTKey) -> bool; fn validate_hash(&self, data: &[u8], dht_key: &PublicKey) -> bool;
fn validate_hash_reader( fn validate_hash_reader(
&self, &self,
reader: &mut dyn std::io::Read, reader: &mut dyn std::io::Read,
dht_key: &DHTKey, dht_key: &PublicKey,
) -> Result<bool, VeilidAPIError>; ) -> Result<bool, VeilidAPIError>;
// Distance Metric // Distance Metric
fn distance(&self, key1: &DHTKey, key2: &DHTKey) -> DHTKeyDistance; fn distance(&self, key1: &PublicKey, key2: &PublicKey) -> PublicKeyDistance;
// Authentication // Authentication
fn sign( fn sign(
&self, &self,
dht_key: &DHTKey, dht_key: &PublicKey,
dht_key_secret: &DHTKeySecret, dht_key_secret: &SecretKey,
data: &[u8], data: &[u8],
) -> Result<DHTSignature, VeilidAPIError>; ) -> Result<Signature, VeilidAPIError>;
fn verify( fn verify(
&self, &self,
dht_key: &DHTKey, dht_key: &PublicKey,
data: &[u8], data: &[u8],
signature: &DHTSignature, signature: &Signature,
) -> Result<(), VeilidAPIError>; ) -> Result<(), VeilidAPIError>;
// AEAD Encrypt/Decrypt // AEAD Encrypt/Decrypt

View File

@ -1,73 +1,65 @@
#![allow(dead_code)] #![allow(dead_code)]
#![allow(clippy::absurd_extreme_comparisons)] #![allow(clippy::absurd_extreme_comparisons)]
use super::*; use super::*;
use crate::routing_table::VersionRange;
use crate::*; use crate::*;
use core::convert::TryInto; use core::convert::TryInto;
/// Envelopes are versioned along with crypto versions /// Envelopes are versioned
/// ///
/// These are the formats for the on-the-wire serialization performed by this module /// These are the formats for the on-the-wire serialization performed by this module
/// ///
/// #[repr(C, packed)] /// #[repr(C, packed)]
/// struct EnvelopeHeader { /// struct EnvelopeHeader {
/// // Size is at least 8 bytes. Depending on the version specified, the size may vary and should be case to the appropriate struct /// // Size is at least 4 bytes. Depending on the version specified, the size may vary and should be case to the appropriate struct
/// magic: [u8; 4], // 0x00: 0x56 0x4C 0x49 0x44 ("VLID") /// magic: [u8; 3], // 0x00: 0x56 0x4C 0x44 ("VLD")
/// version: u8, // 0x04: 0 = EnvelopeV0 /// version: u8, // 0x03: 0 = EnvelopeV0
/// min_version: u8, // 0x05: 0 = EnvelopeV0
/// max_version: u8, // 0x06: 0 = EnvelopeV0
/// reserved: u8, // 0x07: Reserved for future use
/// } /// }
/// ///
/// #[repr(C, packed)] /// #[repr(C, packed)]
/// struct EnvelopeV0 { /// struct EnvelopeV0 {
/// // Size is 106 bytes. /// // Size is 106 bytes without signature and 170 with signature
/// magic: [u8; 4], // 0x00: 0x56 0x4C 0x49 0x44 ("VLID") /// magic: [u8; 3], // 0x00: 0x56 0x4C 0x44 ("VLD")
/// version: u8, // 0x04: 0 = EnvelopeV0 /// version: u8, // 0x03: 0 = EnvelopeV0
/// min_version: u8, // 0x05: 0 = EnvelopeV0 /// crypto_kind: [u8; 4], // 0x04: CryptoSystemVersion FOURCC code (CryptoKind)
/// max_version: u8, // 0x06: 0 = EnvelopeV0
/// reserved: u8, // 0x07: Reserved for future use
/// size: u16, // 0x08: Total size of the envelope including the encrypted operations message. Maximum size is 65,507 bytes, which is the data size limit for a single UDP message on IPv4. /// size: u16, // 0x08: Total size of the envelope including the encrypted operations message. Maximum size is 65,507 bytes, which is the data size limit for a single UDP message on IPv4.
/// timestamp: u64, // 0x0A: Duration since UNIX_EPOCH in microseconds when this message is sent. Messages older than 10 seconds are dropped. /// timestamp: u64, // 0x0A: Duration since UNIX_EPOCH in microseconds when this message is sent. Messages older than 10 seconds are dropped.
/// nonce: [u8; 24], // 0x12: Random nonce for replay protection and for x25519 /// nonce: [u8; 24], // 0x12: Random nonce for replay protection and for dh
/// sender_id: [u8; 32], // 0x2A: Node ID of the message source, which is the Ed25519 public key of the sender (must be verified with find_node if this is a new node_id/address combination) /// sender_id: [u8; 32], // 0x2A: Node ID of the message source, which is the public key of the sender (must be verified with find_node if this is a new node_id/address combination)
/// recipient_id: [u8; 32], // 0x4A: Node ID of the intended recipient, which is the Ed25519 public key of the recipient (must be the receiving node, or a relay lease holder) /// recipient_id: [u8; 32], // 0x4A: Node ID of the intended recipient, which is the public key of the recipient (must be the receiving node, or a relay lease holder)
/// // 0x6A: message is appended (operations) /// // 0x6A: message is appended (operations)
/// // encrypted by XChaCha20Poly1305(nonce,x25519(recipient_id, sender_secret_key)) /// signature: [u8; 64], // 0x?? (end-0x40): Signature of the entire envelope including header is appended to the packet
/// signature: [u8; 64], // 0x?? (end-0x40): Ed25519 signature of the entire envelope including header is appended to the packet
/// // entire header needs to be included in message digest, relays are not allowed to modify the envelope without invalidating the signature. /// // entire header needs to be included in message digest, relays are not allowed to modify the envelope without invalidating the signature.
/// } /// }
pub const MAX_ENVELOPE_SIZE: usize = 65507; pub const MAX_ENVELOPE_SIZE: usize = 65507;
pub const MIN_ENVELOPE_SIZE: usize = 0x6A + 0x40; // Header + Signature pub const MIN_ENVELOPE_SIZE: usize = 0x6A + 0x40; // Header + Signature
pub const ENVELOPE_MAGIC: &[u8; 4] = b"VLID"; pub const ENVELOPE_MAGIC: &[u8; 3] = b"VLD";
pub type EnvelopeNonce = [u8; 24];
#[derive(Debug, Clone, PartialEq, Eq, Default)] #[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Envelope { pub struct Envelope {
version: u8, version: u8,
min_version: u8, crypto_kind: CryptoKind,
max_version: u8,
timestamp: Timestamp, timestamp: Timestamp,
nonce: EnvelopeNonce, nonce: Nonce,
sender_id: DHTKey, sender_id: PublicKey,
recipient_id: DHTKey, recipient_id: PublicKey,
} }
impl Envelope { impl Envelope {
pub fn new( pub fn new(
version: u8, version: u8,
crypto_kind: CryptoKind,
timestamp: Timestamp, timestamp: Timestamp,
nonce: EnvelopeNonce, nonce: Nonce,
sender_id: DHTKey, sender_id: PublicKey,
recipient_id: DHTKey, recipient_id: PublicKey,
) -> Self { ) -> Self {
assert!(version >= MIN_CRYPTO_VERSION); assert!(version >= MIN_ENVELOPE_VERSION);
assert!(version <= MAX_CRYPTO_VERSION); assert!(version <= MAX_ENVELOPE_VERSION);
assert!(VALID_CRYPTO_KINDS.contains(&crypto_kind));
Self { Self {
version, version,
min_version: MIN_CRYPTO_VERSION, crypto_kind,
max_version: MAX_CRYPTO_VERSION,
timestamp, timestamp,
nonce, nonce,
sender_id, sender_id,
@ -75,7 +67,7 @@ impl Envelope {
} }
} }
pub fn from_signed_data(data: &[u8]) -> Result<Envelope, VeilidAPIError> { pub fn from_signed_data(crypto: Crypto, data: &[u8]) -> Result<Envelope, VeilidAPIError> {
// Ensure we are at least the length of the envelope // 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 // Silent drop here, as we use zero length packets as part of the protocol for hole punching
if data.len() < MIN_ENVELOPE_SIZE { if data.len() < MIN_ENVELOPE_SIZE {
@ -83,33 +75,28 @@ impl Envelope {
} }
// Verify magic number // Verify magic number
let magic: [u8; 4] = data[0x00..0x04] let magic: [u8; 3] = data[0x00..0x03]
.try_into() .try_into()
.map_err(VeilidAPIError::internal)?; .map_err(VeilidAPIError::internal)?;
if magic != *ENVELOPE_MAGIC { if magic != *ENVELOPE_MAGIC {
apibail_generic!("bad magic number"); apibail_generic!("bad magic number");
} }
// Check version // Check envelope version
let version = data[0x04]; let version = data[0x03];
if version > MAX_CRYPTO_VERSION || version < MIN_CRYPTO_VERSION { if version > MAX_ENVELOPE_VERSION || version < MIN_ENVELOPE_VERSION {
apibail_parse_error!("unsupported cryptography version", version); apibail_parse_error!("unsupported envelope version", version);
} }
// Get min version // Check crypto kind
let min_version = data[0x05]; let crypto_kind = CryptoKind(
if min_version > version { data[0x04..0x08]
apibail_parse_error!("version too low", version); .try_into()
} .map_err(VeilidAPIError::internal)?,
);
// Get max version let Some(vcrypto) = crypto.get(crypto_kind) else {
let max_version = data[0x06]; apibail_parse_error!("unsupported crypto kind", crypto_kind);
if version > max_version { };
apibail_parse_error!("version too high", version);
}
if min_version > max_version {
apibail_generic!("version information invalid");
}
// Get size and ensure it matches the size of the envelope and is less than the maximum message size // 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( let size: u16 = u16::from_le_bytes(
@ -140,17 +127,18 @@ impl Envelope {
.into(); .into();
// Get nonce and sender node id // Get nonce and sender node id
let nonce: EnvelopeNonce = data[0x12..0x2A] let nonce_slice: [u8; NONCE_LENGTH] = data[0x12..0x2A]
.try_into() .try_into()
.map_err(VeilidAPIError::internal)?; .map_err(VeilidAPIError::internal)?;
let sender_id_slice: [u8; 32] = data[0x2A..0x4A] let sender_id_slice: [u8; PUBLIC_KEY_LENGTH] = data[0x2A..0x4A]
.try_into() .try_into()
.map_err(VeilidAPIError::internal)?; .map_err(VeilidAPIError::internal)?;
let recipient_id_slice: [u8; 32] = data[0x4A..0x6A] let recipient_id_slice: [u8; PUBLIC_KEY_LENGTH] = data[0x4A..0x6A]
.try_into() .try_into()
.map_err(VeilidAPIError::internal)?; .map_err(VeilidAPIError::internal)?;
let sender_id = DHTKey::new(sender_id_slice); let nonce: Nonce = Nonce::new(nonce_slice);
let recipient_id = DHTKey::new(recipient_id_slice); let sender_id = PublicKey::new(sender_id_slice);
let recipient_id = PublicKey::new(recipient_id_slice);
// Ensure sender_id and recipient_id are not the same // Ensure sender_id and recipient_id are not the same
if sender_id == recipient_id { if sender_id == recipient_id {
@ -161,21 +149,21 @@ impl Envelope {
} }
// Get signature // Get signature
let signature = DHTSignature::new( let signature = Signature::new(
data[(data.len() - 64)..] data[(data.len() - 64)..]
.try_into() .try_into()
.map_err(VeilidAPIError::internal)?, .map_err(VeilidAPIError::internal)?,
); );
// Validate signature // Validate signature
verify(&sender_id, &data[0..(data.len() - 64)], &signature) vcrypto
.verify(&sender_id, &data[0..(data.len() - 64)], &signature)
.map_err(VeilidAPIError::internal)?; .map_err(VeilidAPIError::internal)?;
// Return envelope // Return envelope
Ok(Self { Ok(Self {
version, version,
min_version, crypto_kind,
max_version,
timestamp, timestamp,
nonce, nonce,
sender_id, sender_id,
@ -187,10 +175,12 @@ impl Envelope {
&self, &self,
crypto: Crypto, crypto: Crypto,
data: &[u8], data: &[u8],
node_id_secret: &DHTKeySecret, node_id_secret: &SecretKey,
) -> Result<Vec<u8>, VeilidAPIError> { ) -> Result<Vec<u8>, VeilidAPIError> {
// Get DH secret // Get DH secret
let vcrypto = crypto.get(self.version)?; let vcrypto = crypto
.get(self.crypto_kind)
.expect("need to ensure only valid crypto kinds here");
let dh_secret = vcrypto.cached_dh(&self.sender_id, node_id_secret)?; let dh_secret = vcrypto.cached_dh(&self.sender_id, node_id_secret)?;
// Decrypt message without authentication // Decrypt message without authentication
@ -204,40 +194,41 @@ impl Envelope {
&self, &self,
crypto: Crypto, crypto: Crypto,
body: &[u8], body: &[u8],
node_id_secret: &DHTKeySecret, node_id_secret: &SecretKey,
) -> Result<Vec<u8>, VeilidAPIError> { ) -> Result<Vec<u8>, VeilidAPIError> {
// Ensure body isn't too long // Ensure body isn't too long
let envelope_size: usize = body.len() + MIN_ENVELOPE_SIZE; let envelope_size: usize = body.len() + MIN_ENVELOPE_SIZE;
if envelope_size > MAX_ENVELOPE_SIZE { if envelope_size > MAX_ENVELOPE_SIZE {
apibail_parse_error!("envelope size is too large", envelope_size); apibail_parse_error!("envelope size is too large", envelope_size);
} }
// Generate dh secret
let vcrypto = crypto
.get(self.crypto_kind)
.expect("need to ensure only valid crypto kinds here");
let dh_secret = vcrypto.cached_dh(&self.recipient_id, node_id_secret)?;
// Write envelope body
let mut data = vec![0u8; envelope_size]; let mut data = vec![0u8; envelope_size];
// Write magic // Write magic
data[0x00..0x04].copy_from_slice(ENVELOPE_MAGIC); data[0x00..0x03].copy_from_slice(ENVELOPE_MAGIC);
// Write version // Write version
data[0x04] = self.version; data[0x03] = self.version;
// Write min version // Write crypto kind
data[0x05] = self.min_version; data[0x04..0x08].copy_from_slice(&self.crypto_kind.0);
// Write max version
data[0x06] = self.max_version;
// Write size // Write size
data[0x08..0x0A].copy_from_slice(&(envelope_size as u16).to_le_bytes()); data[0x08..0x0A].copy_from_slice(&(envelope_size as u16).to_le_bytes());
// Write timestamp // Write timestamp
data[0x0A..0x12].copy_from_slice(&self.timestamp.as_u64().to_le_bytes()); data[0x0A..0x12].copy_from_slice(&self.timestamp.as_u64().to_le_bytes());
// Write nonce // Write nonce
data[0x12..0x2A].copy_from_slice(&self.nonce); data[0x12..0x2A].copy_from_slice(&self.nonce.bytes);
// Write sender node id // Write sender node id
data[0x2A..0x4A].copy_from_slice(&self.sender_id.bytes); data[0x2A..0x4A].copy_from_slice(&self.sender_id.bytes);
// Write recipient node id // Write recipient node id
data[0x4A..0x6A].copy_from_slice(&self.recipient_id.bytes); data[0x4A..0x6A].copy_from_slice(&self.recipient_id.bytes);
// Generate dh secret
let vcrypto = crypto.get(self.version)?;
let dh_secret = vcrypto.cached_dh(&self.recipient_id, node_id_secret)?;
// Encrypt and authenticate message // Encrypt and authenticate message
let encrypted_body = vcrypto.crypt_no_auth_aligned_8(body, &self.nonce, &dh_secret); let encrypted_body = vcrypto.crypt_no_auth_unaligned(body, &self.nonce, &dh_secret);
// Write body // Write body
if !encrypted_body.is_empty() { if !encrypted_body.is_empty() {
@ -245,7 +236,7 @@ impl Envelope {
} }
// Sign the envelope // Sign the envelope
let signature = sign( let signature = vcrypto.sign(
&self.sender_id, &self.sender_id,
node_id_secret, node_id_secret,
&data[0..(envelope_size - 64)], &data[0..(envelope_size - 64)],
@ -261,25 +252,22 @@ impl Envelope {
self.version self.version
} }
pub fn get_min_max_version(&self) -> VersionRange { pub fn get_crypto_kind(&self) -> CryptoKind {
VersionRange { self.crypto_kind
min: self.min_version,
max: self.max_version,
}
} }
pub fn get_timestamp(&self) -> Timestamp { pub fn get_timestamp(&self) -> Timestamp {
self.timestamp self.timestamp
} }
pub fn get_nonce(&self) -> EnvelopeNonce { pub fn get_nonce(&self) -> Nonce {
self.nonce self.nonce
} }
pub fn get_sender_id(&self) -> DHTKey { pub fn get_sender_id(&self) -> PublicKey {
self.sender_id self.sender_id
} }
pub fn get_recipient_id(&self) -> DHTKey { pub fn get_recipient_id(&self) -> PublicKey {
self.recipient_id self.recipient_id
} }
} }

View File

@ -1,21 +1,20 @@
mod byte_array_types;
mod envelope; mod envelope;
mod key;
mod receipt; mod receipt;
mod types;
mod value; mod value;
pub mod crypto_system; pub mod crypto_system;
pub mod tests; pub mod tests;
pub mod v0; pub mod vld0;
pub use byte_array_types::*;
pub use crypto_system::*; pub use crypto_system::*;
pub use envelope::*; pub use envelope::*;
pub use key::*;
pub use receipt::*; pub use receipt::*;
pub use types::*;
pub use value::*; pub use value::*;
pub use vld0::*;
pub type CryptoVersion = u8;
pub const MIN_CRYPTO_VERSION: CryptoVersion = 0u8;
pub const MAX_CRYPTO_VERSION: CryptoVersion = 0u8;
use crate::*; use crate::*;
use core::convert::TryInto; use core::convert::TryInto;
@ -23,17 +22,18 @@ use hashlink::linked_hash_map::Entry;
use hashlink::LruCache; use hashlink::LruCache;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
pub type SharedSecret = [u8; 32];
pub type Nonce = [u8; 24];
pub type CryptoSystemVersion = Arc<dyn CryptoSystem + Send + Sync>; pub type CryptoSystemVersion = Arc<dyn CryptoSystem + Send + Sync>;
pub const VALID_CRYPTO_KINDS: [CryptoKind; 1] = [CRYPTO_KIND_VLD0];
pub const MIN_ENVELOPE_VERSION: u8 = 0u8;
pub const MAX_ENVELOPE_VERSION: u8 = 0u8;
const DH_CACHE_SIZE: usize = 4096; const DH_CACHE_SIZE: usize = 4096;
#[derive(Serialize, Deserialize, PartialEq, Eq, Hash)] #[derive(Serialize, Deserialize, PartialEq, Eq, Hash)]
struct DHCacheKey { struct DHCacheKey {
key: DHTKey, key: PublicKey,
secret: DHTKeySecret, secret: SecretKey,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -48,7 +48,7 @@ fn cache_to_bytes(cache: &DHCache) -> Vec<u8> {
for e in cache.iter() { for e in cache.iter() {
out.extend(&e.0.key.bytes); out.extend(&e.0.key.bytes);
out.extend(&e.0.secret.bytes); out.extend(&e.0.secret.bytes);
out.extend(&e.1.shared_secret); out.extend(&e.1.shared_secret.bytes);
} }
let mut rev: Vec<u8> = Vec::with_capacity(out.len()); let mut rev: Vec<u8> = Vec::with_capacity(out.len());
for d in out.chunks(32 + 32 + 32).rev() { for d in out.chunks(32 + 32 + 32).rev() {
@ -60,70 +60,101 @@ fn cache_to_bytes(cache: &DHCache) -> Vec<u8> {
fn bytes_to_cache(bytes: &[u8], cache: &mut DHCache) { fn bytes_to_cache(bytes: &[u8], cache: &mut DHCache) {
for d in bytes.chunks(32 + 32 + 32) { for d in bytes.chunks(32 + 32 + 32) {
let k = DHCacheKey { let k = DHCacheKey {
key: DHTKey::new(d[0..32].try_into().expect("asdf")), key: PublicKey::new(d[0..32].try_into().expect("asdf")),
secret: DHTKeySecret::new(d[32..64].try_into().expect("asdf")), secret: SecretKey::new(d[32..64].try_into().expect("asdf")),
}; };
let v = DHCacheValue { let v = DHCacheValue {
shared_secret: d[64..96].try_into().expect("asdf"), shared_secret: SharedSecret::new(d[64..96].try_into().expect("asdf")),
}; };
cache.insert(k, v); cache.insert(k, v);
} }
} }
struct CryptoInner { struct CryptoInner {
table_store: TableStore,
node_id: DHTKey,
node_id_secret: DHTKeySecret,
dh_cache: DHCache, dh_cache: DHCache,
flush_future: Option<SendPinBoxFuture<()>>, flush_future: Option<SendPinBoxFuture<()>>,
crypto_v0: Option<Arc<dyn CryptoSystem + Send + Sync>>, crypto_vld0: Option<Arc<dyn CryptoSystem + Send + Sync>>,
} }
struct CryptoUnlockedInner {
config: VeilidConfig,
table_store: TableStore,
protected_store: ProtectedStore,
}
/// Crypto factory implementation
#[derive(Clone)] #[derive(Clone)]
pub struct Crypto { pub struct Crypto {
config: VeilidConfig, unlocked_inner: Arc<CryptoUnlockedInner>,
inner: Arc<Mutex<CryptoInner>>, inner: Arc<Mutex<CryptoInner>>,
} }
impl Crypto { impl Crypto {
fn new_inner(table_store: TableStore) -> CryptoInner { fn new_inner() -> CryptoInner {
CryptoInner { CryptoInner {
table_store,
node_id: Default::default(),
node_id_secret: Default::default(),
dh_cache: DHCache::new(DH_CACHE_SIZE), dh_cache: DHCache::new(DH_CACHE_SIZE),
flush_future: None, flush_future: None,
crypto_v0: None, crypto_vld0: None,
} }
} }
pub fn new(config: VeilidConfig, table_store: TableStore) -> Self { pub fn new(
config: VeilidConfig,
table_store: TableStore,
protected_store: ProtectedStore,
) -> Self {
let out = Self { let out = Self {
config, unlocked_inner: Arc::new(CryptoUnlockedInner {
inner: Arc::new(Mutex::new(Self::new_inner(table_store))), config,
table_store,
protected_store,
}),
inner: Arc::new(Mutex::new(Self::new_inner())),
}; };
out.inner.lock().crypto_v0 = Some(Arc::new(v0::CryptoV0System::new(out.clone()))); out.inner.lock().crypto_vld0 = Some(Arc::new(vld0::CryptoSystemVLD0::new(out.clone())));
out out
} }
pub async fn init(&self) -> EyreResult<()> { pub async fn init(&self) -> EyreResult<()> {
trace!("Crypto::init"); trace!("Crypto::init");
let table_store = self.unlocked_inner.table_store.clone();
// Init node id from config
if let Err(e) = self
.unlocked_inner
.config
.init_node_ids(self.clone(), self.unlocked_inner.protected_store.clone())
.await
{
return Err(e).wrap_err("init node id failed");
}
// make local copy of node id for easy access // make local copy of node id for easy access
let (table_store, node_id) = { let mut cache_validity_key: Vec<u8> = Vec::new();
let mut inner = self.inner.lock(); {
let c = self.config.get(); let c = self.unlocked_inner.config.get();
inner.node_id = c.network.node_id.unwrap(); for ck in &VALID_CRYPTO_KINDS {
inner.node_id_secret = c.network.node_id_secret.unwrap(); cache_validity_key.append(
(inner.table_store.clone(), c.network.node_id) &mut c
.network
.routing_table
.node_ids
.get(ck)
.unwrap()
.node_id
.unwrap()
.bytes
.to_vec(),
);
}
}; };
// load caches if they are valid for this node id // load caches if they are valid for this node id
let mut db = table_store.open("crypto_caches", 1).await?; let mut db = table_store.open("crypto_caches", 1).await?;
let caches_valid = match db.load(0, b"node_id")? { let caches_valid = match db.load(0, b"cache_validity_key")? {
Some(v) => v.as_slice() == node_id.unwrap().bytes, Some(v) => v == cache_validity_key,
None => false, None => false,
}; };
if caches_valid { if caches_valid {
@ -135,7 +166,8 @@ impl Crypto {
drop(db); drop(db);
table_store.delete("crypto_caches").await?; table_store.delete("crypto_caches").await?;
db = table_store.open("crypto_caches", 1).await?; db = table_store.open("crypto_caches", 1).await?;
db.store(0, b"node_id", &node_id.unwrap().bytes).await?; db.store(0, b"cache_validity_key", &cache_validity_key)
.await?;
} }
// Schedule flushing // Schedule flushing
@ -155,13 +187,16 @@ impl Crypto {
pub async fn flush(&self) -> EyreResult<()> { pub async fn flush(&self) -> EyreResult<()> {
//trace!("Crypto::flush"); //trace!("Crypto::flush");
let (table_store, cache_bytes) = { let cache_bytes = {
let inner = self.inner.lock(); let inner = self.inner.lock();
let cache_bytes = cache_to_bytes(&inner.dh_cache); cache_to_bytes(&inner.dh_cache)
(inner.table_store.clone(), cache_bytes)
}; };
let db = table_store.open("crypto_caches", 1).await?; let db = self
.unlocked_inner
.table_store
.open("crypto_caches", 1)
.await?;
db.store(0, b"dh_cache", &cache_bytes).await?; db.store(0, b"dh_cache", &cache_bytes).await?;
Ok(()) Ok(())
} }
@ -183,26 +218,67 @@ impl Crypto {
}; };
} }
// Factory /// Factory method to get a specific crypto version
fn get(&self, version: CryptoVersion) -> Result<CryptoSystemVersion, VeilidAPIError> { pub fn get(&self, kind: CryptoKind) -> Option<CryptoSystemVersion> {
let inner = self.inner.lock(); let inner = self.inner.lock();
match version { match kind {
0u8 => Ok(inner.crypto_v0.clone().unwrap()), CRYPTO_KIND_VLD0 => Some(inner.crypto_vld0.clone().unwrap()),
_ => Err(VeilidAPIError::InvalidArgument { _ => None,
context: "Unsupported crypto version".to_owned(),
argument: "version".to_owned(),
value: format!("{}", version),
}),
} }
} }
/// Signature set verification
/// Returns the set of signature cryptokinds that validate and are supported
/// If any cryptokinds are supported and do not validate, the whole operation
/// returns an error
pub fn verify_signatures<F, R>(
&self,
data: &[u8],
signatures: &[TypedKeySignature],
transform: F,
) -> Result<Vec<R>, VeilidAPIError>
where
F: Fn(&TypedKeySignature) -> R,
{
let mut out = Vec::<R>::with_capacity(signatures.len());
for sig in signatures {
if let Some(vcrypto) = self.get(sig.kind) {
vcrypto.verify(&sig.key, data, &sig.signature)?;
out.push(transform(sig));
}
}
Ok(out)
}
/// Signature set generation
/// Generates the set of signatures that are supported
/// Any cryptokinds that are not supported are silently dropped
pub fn generate_signatures<F, R>(
&self,
data: &[u8],
keypairs: &[TypedKeyPair],
transform: F,
) -> Result<Vec<R>, VeilidAPIError>
where
F: Fn(&TypedKeyPair, Signature) -> R,
{
let mut out = Vec::<R>::with_capacity(keypairs.len());
for kp in keypairs {
if let Some(vcrypto) = self.get(kp.kind) {
let sig = vcrypto.sign(&kp.key, &kp.secret, data)?;
out.push(transform(kp, sig))
}
}
Ok(out)
}
// Internal utilities // Internal utilities
fn cached_dh_internal<T: CryptoSystem>( fn cached_dh_internal<T: CryptoSystem>(
&self, &self,
vcrypto: &T, vcrypto: &T,
key: &DHTKey, key: &PublicKey,
secret: &DHTKeySecret, secret: &SecretKey,
) -> Result<SharedSecret, VeilidAPIError> { ) -> Result<SharedSecret, VeilidAPIError> {
Ok( Ok(
match self.inner.lock().dh_cache.entry(DHCacheKey { match self.inner.lock().dh_cache.entry(DHCacheKey {

View File

@ -3,64 +3,57 @@
use super::*; use super::*;
use crate::*; use crate::*;
use core::convert::TryInto; use core::convert::TryInto;
use data_encoding::BASE64URL_NOPAD;
/// Out-of-band receipts are versioned along with crypto versions /// Out-of-band receipts are versioned along with envelope versions
/// ///
/// These are the formats for the on-the-wire serialization performed by this module /// These are the formats for the on-the-wire serialization performed by this module
/// ///
/// #[repr(C, packed)] /// #[repr(C, packed)]
/// struct ReceiptHeader { /// struct ReceiptHeader {
/// // Size is at least 8 bytes. Depending on the version specified, the size may vary and should be case to the appropriate struct /// // Size is at least 4 bytes. Depending on the version specified, the size may vary and should be case to the appropriate struct
/// magic: [u8; 4], // 0x00: 0x52 0x43 0x50 0x54 ("RCPT") /// magic: [u8; 3], // 0x00: 0x52 0x43 0x50 ("RCP")
/// version: u8, // 0x04: 0 = ReceiptV0 /// version: u8, // 0x03: 0 = ReceiptV0
/// reserved: u8, // 0x05: Reserved for future use
/// } /// }
/// ///
/// #[repr(C, packed)] /// #[repr(C, packed)]
/// struct ReceiptV0 { /// struct ReceiptV0 {
/// // Size is 106 bytes. /// // Size is 66 bytes without extra data and signature, 130 with signature
/// magic: [u8; 4], // 0x00: 0x52 0x43 0x50 0x54 ("RCPT") /// magic: [u8; 3], // 0x00: 0x52 0x43 0x50 ("RCP")
/// version: u8, // 0x04: 0 = ReceiptV0 /// version: u8, // 0x03: 0 = ReceiptV0
/// reserved: u8, // 0x05: Reserved for future use /// crypto_kind: [u8; 4], // 0x04: CryptoSystemVersion FOURCC code
/// size: u16, // 0x06: Total size of the receipt including the extra data and the signature. Maximum size is 1152 bytes. /// size: u16, // 0x08: Total size of the receipt including the extra data and the signature. Maximum size is 1380 bytes.
/// nonce: [u8; 24], // 0x08: Randomly chosen bytes that represent a unique receipt. Could be used to encrypt the extra data, but it's not required. /// nonce: [u8; 24], // 0x0A: Randomly chosen bytes that represent a unique receipt. Could be used to encrypt the extra data, but it's not required.
/// sender_id: [u8; 32], // 0x20: Node ID of the message source, which is the Ed25519 public key of the sender /// sender_id: [u8; 32], // 0x22: Node ID of the message source, which is the public key of the sender
/// extra_data: [u8; ??], // 0x40: Extra data is appended (arbitrary extra data, not encrypted by receipt itself, maximum size is 1024 bytes) /// extra_data: [u8; ??], // 0x42: Extra data is appended (arbitrary extra data, not encrypted by receipt itself, maximum size is 1250 bytes)
/// signature: [u8; 64], // 0x?? (end-0x40): Ed25519 signature of the entire receipt including header and extra data is appended to the packet /// signature: [u8; 64], // 0x?? (end-0x40): Signature of the entire receipt including header and extra data is appended to the packet
/// } /// }
pub const MAX_RECEIPT_SIZE: usize = 1152; pub const MAX_RECEIPT_SIZE: usize = 1380;
pub const MAX_EXTRA_DATA_SIZE: usize = 1024; pub const MAX_EXTRA_DATA_SIZE: usize = MAX_RECEIPT_SIZE - MIN_RECEIPT_SIZE; // 1250
pub const MIN_RECEIPT_SIZE: usize = 128; pub const MIN_RECEIPT_SIZE: usize = 130;
pub const RECEIPT_MAGIC: &[u8; 4] = b"RCPT"; pub const RECEIPT_MAGIC: &[u8; 3] = b"RCP";
pub type ReceiptNonce = [u8; 24];
pub trait Encodable {
fn encode(&self) -> String;
}
impl Encodable for ReceiptNonce {
fn encode(&self) -> String {
BASE64URL_NOPAD.encode(self)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)] #[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Receipt { pub struct Receipt {
version: u8, version: u8,
nonce: ReceiptNonce, crypto_kind: CryptoKind,
sender_id: DHTKey, nonce: Nonce,
sender_id: PublicKey,
extra_data: Vec<u8>, extra_data: Vec<u8>,
} }
impl Receipt { impl Receipt {
pub fn try_new<D: AsRef<[u8]>>( pub fn try_new<D: AsRef<[u8]>>(
version: u8, version: u8,
nonce: ReceiptNonce, crypto_kind: CryptoKind,
sender_id: DHTKey, nonce: Nonce,
sender_id: PublicKey,
extra_data: D, extra_data: D,
) -> Result<Self, VeilidAPIError> { ) -> Result<Self, VeilidAPIError> {
assert!(version >= MIN_ENVELOPE_VERSION);
assert!(version <= MAX_ENVELOPE_VERSION);
assert!(VALID_CRYPTO_KINDS.contains(&crypto_kind));
if extra_data.as_ref().len() > MAX_EXTRA_DATA_SIZE { if extra_data.as_ref().len() > MAX_EXTRA_DATA_SIZE {
apibail_parse_error!( apibail_parse_error!(
"extra data too large for receipt", "extra data too large for receipt",
@ -69,20 +62,21 @@ impl Receipt {
} }
Ok(Self { Ok(Self {
version, version,
crypto_kind,
nonce, nonce,
sender_id, sender_id,
extra_data: Vec::from(extra_data.as_ref()), extra_data: Vec::from(extra_data.as_ref()),
}) })
} }
pub fn from_signed_data(data: &[u8]) -> Result<Receipt, VeilidAPIError> { pub fn from_signed_data(crypto: Crypto, data: &[u8]) -> Result<Receipt, VeilidAPIError> {
// Ensure we are at least the length of the envelope // Ensure we are at least the length of the envelope
if data.len() < MIN_RECEIPT_SIZE { if data.len() < MIN_RECEIPT_SIZE {
apibail_parse_error!("receipt too small", data.len()); apibail_parse_error!("receipt too small", data.len());
} }
// Verify magic number // Verify magic number
let magic: [u8; 4] = data[0x00..0x04] let magic: [u8; 3] = data[0x00..0x03]
.try_into() .try_into()
.map_err(VeilidAPIError::internal)?; .map_err(VeilidAPIError::internal)?;
if magic != *RECEIPT_MAGIC { if magic != *RECEIPT_MAGIC {
@ -90,14 +84,24 @@ impl Receipt {
} }
// Check version // Check version
let version = data[0x04]; let version = data[0x03];
if version > MAX_CRYPTO_VERSION || version < MIN_CRYPTO_VERSION { if version > MAX_ENVELOPE_VERSION || version < MIN_ENVELOPE_VERSION {
apibail_parse_error!("unsupported cryptography version", version); apibail_parse_error!("unsupported envelope version", version);
} }
// Check crypto kind
let crypto_kind = CryptoKind(
data[0x04..0x08]
.try_into()
.map_err(VeilidAPIError::internal)?,
);
let Some(vcrypto) = crypto.get(crypto_kind) else {
apibail_parse_error!("unsupported crypto kind", crypto_kind);
};
// Get size and ensure it matches the size of the envelope and is less than the maximum message size // 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( let size: u16 = u16::from_le_bytes(
data[0x06..0x08] data[0x08..0x0A]
.try_into() .try_into()
.map_err(VeilidAPIError::internal)?, .map_err(VeilidAPIError::internal)?,
); );
@ -112,64 +116,80 @@ impl Receipt {
} }
// Get sender id // Get sender id
let sender_id = DHTKey::new( let sender_id = PublicKey::new(
data[0x20..0x40] data[0x22..0x42]
.try_into() .try_into()
.map_err(VeilidAPIError::internal)?, .map_err(VeilidAPIError::internal)?,
); );
// Get signature // Get signature
let signature = DHTSignature::new( let signature = Signature::new(
data[(data.len() - 64)..] data[(data.len() - 64)..]
.try_into() .try_into()
.map_err(VeilidAPIError::internal)?, .map_err(VeilidAPIError::internal)?,
); );
// Validate signature // Validate signature
verify(&sender_id, &data[0..(data.len() - 64)], &signature) vcrypto
.verify(&sender_id, &data[0..(data.len() - 64)], &signature)
.map_err(VeilidAPIError::generic)?; .map_err(VeilidAPIError::generic)?;
// Get nonce // Get nonce
let nonce: ReceiptNonce = data[0x08..0x20] let nonce: Nonce = Nonce::new(
.try_into() data[0x0A..0x22]
.map_err(VeilidAPIError::internal)?; .try_into()
.map_err(VeilidAPIError::internal)?,
);
// Get extra data and signature // Get extra data and signature
let extra_data: Vec<u8> = Vec::from(&data[0x40..(data.len() - 64)]); let extra_data: Vec<u8> = Vec::from(&data[0x42..(data.len() - 64)]);
// Return receipt // Return receipt
Ok(Self { Ok(Self {
version, version,
crypto_kind,
nonce, nonce,
sender_id, sender_id,
extra_data, extra_data,
}) })
} }
pub fn to_signed_data(&self, secret: &DHTKeySecret) -> Result<Vec<u8>, VeilidAPIError> { pub fn to_signed_data(
&self,
crypto: Crypto,
secret: &SecretKey,
) -> Result<Vec<u8>, VeilidAPIError> {
// Ensure extra data isn't too long // Ensure extra data isn't too long
let receipt_size: usize = self.extra_data.len() + MIN_RECEIPT_SIZE; let receipt_size: usize = self.extra_data.len() + MIN_RECEIPT_SIZE;
if receipt_size > MAX_RECEIPT_SIZE { if receipt_size > MAX_RECEIPT_SIZE {
apibail_parse_error!("receipt too large", receipt_size); apibail_parse_error!("receipt too large", receipt_size);
} }
// Get crypto version
let vcrypto = crypto
.get(self.crypto_kind)
.expect("need to ensure only valid crypto kinds here");
let mut data: Vec<u8> = vec![0u8; receipt_size]; let mut data: Vec<u8> = vec![0u8; receipt_size];
// Write magic // Write magic
data[0x00..0x04].copy_from_slice(RECEIPT_MAGIC); data[0x00..0x03].copy_from_slice(RECEIPT_MAGIC);
// Write version // Write version
data[0x04] = self.version; data[0x03] = self.version;
// Write crypto kind
data[0x04..0x08].copy_from_slice(&self.crypto_kind.0);
// Write size // Write size
data[0x06..0x08].copy_from_slice(&(receipt_size as u16).to_le_bytes()); data[0x08..0x0A].copy_from_slice(&(receipt_size as u16).to_le_bytes());
// Write nonce // Write nonce
data[0x08..0x20].copy_from_slice(&self.nonce); data[0x0A..0x22].copy_from_slice(&self.nonce.bytes);
// Write sender node id // Write sender node id
data[0x20..0x40].copy_from_slice(&self.sender_id.bytes); data[0x22..0x42].copy_from_slice(&self.sender_id.bytes);
// Write extra data // Write extra data
if !self.extra_data.is_empty() { if !self.extra_data.is_empty() {
data[0x40..(receipt_size - 64)].copy_from_slice(self.extra_data.as_slice()); data[0x42..(receipt_size - 64)].copy_from_slice(self.extra_data.as_slice());
} }
// Sign the receipt // Sign the receipt
let signature = sign(&self.sender_id, secret, &data[0..(receipt_size - 64)]) let signature = vcrypto
.sign(&self.sender_id, secret, &data[0..(receipt_size - 64)])
.map_err(VeilidAPIError::generic)?; .map_err(VeilidAPIError::generic)?;
// Append the signature // Append the signature
data[(receipt_size - 64)..].copy_from_slice(&signature.bytes); data[(receipt_size - 64)..].copy_from_slice(&signature.bytes);
@ -181,11 +201,15 @@ impl Receipt {
self.version self.version
} }
pub fn get_nonce(&self) -> ReceiptNonce { pub fn get_crypto_kind(&self) -> CryptoKind {
self.crypto_kind
}
pub fn get_nonce(&self) -> Nonce {
self.nonce self.nonce
} }
pub fn get_sender_id(&self) -> DHTKey { pub fn get_sender_id(&self) -> PublicKey {
self.sender_id self.sender_id
} }
pub fn get_extra_data(&self) -> &[u8] { pub fn get_extra_data(&self) -> &[u8] {

View File

@ -1,6 +1,6 @@
pub mod test_crypto; pub mod test_crypto;
pub mod test_dht_key;
pub mod test_envelope_receipt; pub mod test_envelope_receipt;
pub mod test_types;
use super::*; use super::*;
use crate::tests::common::test_veilid_config::*; use crate::tests::common::test_veilid_config::*;

View File

@ -167,7 +167,7 @@ pub async fn test_all() {
let crypto = api.crypto().unwrap(); let crypto = api.crypto().unwrap();
// Test versions // Test versions
for v in MIN_CRYPTO_VERSION..=MAX_CRYPTO_VERSION { for v in VALID_CRYPTO_KINDS {
let vcrypto = crypto.get(v).unwrap(); let vcrypto = crypto.get(v).unwrap();
test_aead(vcrypto.clone()).await; test_aead(vcrypto.clone()).await;
test_no_auth(vcrypto.clone()).await; test_no_auth(vcrypto.clone()).await;

View File

@ -8,7 +8,14 @@ pub async fn test_envelope_round_trip(vcrypto: CryptoSystemVersion) {
let nonce = vcrypto.random_nonce(); let nonce = vcrypto.random_nonce();
let (sender_id, sender_secret) = vcrypto.generate_keypair(); let (sender_id, sender_secret) = vcrypto.generate_keypair();
let (recipient_id, recipient_secret) = vcrypto.generate_keypair(); let (recipient_id, recipient_secret) = vcrypto.generate_keypair();
let envelope = Envelope::new(vcrypto.version(), ts, nonce, sender_id, recipient_id); let envelope = Envelope::new(
MAX_ENVELOPE_VERSION,
vcrypto.kind(),
ts,
nonce,
sender_id,
recipient_id,
);
// Create arbitrary body // Create arbitrary body
let body = b"This is an arbitrary body"; let body = b"This is an arbitrary body";
@ -19,8 +26,8 @@ pub async fn test_envelope_round_trip(vcrypto: CryptoSystemVersion) {
.expect("failed to encrypt data"); .expect("failed to encrypt data");
// Deserialize from bytes // Deserialize from bytes
let envelope2 = let envelope2 = Envelope::from_signed_data(vcrypto.crypto(), &enc_data)
Envelope::from_signed_data(&enc_data).expect("failed to deserialize envelope from data"); .expect("failed to deserialize envelope from data");
let body2 = envelope2 let body2 = envelope2
.decrypt_body(vcrypto.crypto(), &enc_data, &recipient_secret) .decrypt_body(vcrypto.crypto(), &enc_data, &recipient_secret)
@ -35,13 +42,13 @@ pub async fn test_envelope_round_trip(vcrypto: CryptoSystemVersion) {
let mut mod_enc_data = enc_data.clone(); let mut mod_enc_data = enc_data.clone();
mod_enc_data[enc_data_len - 1] ^= 0x80u8; mod_enc_data[enc_data_len - 1] ^= 0x80u8;
assert!( assert!(
Envelope::from_signed_data(&mod_enc_data).is_err(), Envelope::from_signed_data(vcrypto.crypto(), &mod_enc_data).is_err(),
"should have failed to decode envelope with modified signature" "should have failed to decode envelope with modified signature"
); );
let mut mod_enc_data2 = enc_data.clone(); let mut mod_enc_data2 = enc_data.clone();
mod_enc_data2[enc_data_len - 65] ^= 0x80u8; mod_enc_data2[enc_data_len - 65] ^= 0x80u8;
assert!( assert!(
Envelope::from_signed_data(&mod_enc_data2).is_err(), Envelope::from_signed_data(vcrypto.crypto(), &mod_enc_data2).is_err(),
"should have failed to decode envelope with modified data" "should have failed to decode envelope with modified data"
); );
} }
@ -54,20 +61,21 @@ pub async fn test_receipt_round_trip(vcrypto: CryptoSystemVersion) {
// Create receipt // Create receipt
let nonce = vcrypto.random_nonce(); let nonce = vcrypto.random_nonce();
let (sender_id, sender_secret) = vcrypto.generate_keypair(); let (sender_id, sender_secret) = vcrypto.generate_keypair();
let receipt = Receipt::try_new(0, nonce, sender_id, body).expect("should not fail"); let receipt = Receipt::try_new(MAX_ENVELOPE_VERSION, vcrypto.kind(), nonce, sender_id, body)
.expect("should not fail");
// Serialize to bytes // Serialize to bytes
let mut enc_data = receipt let mut enc_data = receipt
.to_signed_data(&sender_secret) .to_signed_data(vcrypto.crypto(), &sender_secret)
.expect("failed to make signed data"); .expect("failed to make signed data");
// Deserialize from bytes // Deserialize from bytes
let receipt2 = let receipt2 = Receipt::from_signed_data(vcrypto.crypto(), &enc_data)
Receipt::from_signed_data(&enc_data).expect("failed to deserialize envelope from data"); .expect("failed to deserialize envelope from data");
// Should not validate even when a single bit is changed // Should not validate even when a single bit is changed
enc_data[5] = 0x01; enc_data[5] = 0x01;
Receipt::from_signed_data(&enc_data) Receipt::from_signed_data(vcrypto.crypto(), &enc_data)
.expect_err("should have failed to decrypt using wrong secret"); .expect_err("should have failed to decrypt using wrong secret");
// Compare receipts // Compare receipts
@ -79,7 +87,7 @@ pub async fn test_all() {
let crypto = api.crypto().unwrap(); let crypto = api.crypto().unwrap();
// Test versions // Test versions
for v in MIN_CRYPTO_VERSION..=MAX_CRYPTO_VERSION { for v in VALID_CRYPTO_KINDS {
let vcrypto = crypto.get(v).unwrap(); let vcrypto = crypto.get(v).unwrap();
test_envelope_round_trip(vcrypto.clone()).await; test_envelope_round_trip(vcrypto.clone()).await;

View File

@ -5,8 +5,8 @@ use core::convert::TryFrom;
static LOREM_IPSUM:&str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "; static LOREM_IPSUM:&str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ";
static CHEEZBURGER: &str = "I can has cheezburger"; static CHEEZBURGER: &str = "I can has cheezburger";
static EMPTY_KEY: [u8; key::DHT_KEY_LENGTH] = [0u8; key::DHT_KEY_LENGTH]; static EMPTY_KEY: [u8; PUBLIC_KEY_LENGTH] = [0u8; PUBLIC_KEY_LENGTH];
static EMPTY_KEY_SECRET: [u8; key::DHT_KEY_SECRET_LENGTH] = [0u8; key::DHT_KEY_SECRET_LENGTH]; static EMPTY_KEY_SECRET: [u8; SECRET_KEY_LENGTH] = [0u8; SECRET_KEY_LENGTH];
pub async fn test_generate_secret(vcrypto: CryptoSystemVersion) { pub async fn test_generate_secret(vcrypto: CryptoSystemVersion) {
// Verify keys generate // Verify keys generate
@ -119,7 +119,7 @@ pub async fn test_sign_and_verify(vcrypto: CryptoSystemVersion) {
pub async fn test_key_conversions(vcrypto: CryptoSystemVersion) { pub async fn test_key_conversions(vcrypto: CryptoSystemVersion) {
// Test default key // Test default key
let (dht_key, dht_key_secret) = (key::DHTKey::default(), key::DHTKeySecret::default()); let (dht_key, dht_key_secret) = (PublicKey::default(), SecretKey::default());
assert_eq!(dht_key.bytes, EMPTY_KEY); assert_eq!(dht_key.bytes, EMPTY_KEY);
assert_eq!(dht_key_secret.bytes, EMPTY_KEY_SECRET); assert_eq!(dht_key_secret.bytes, EMPTY_KEY_SECRET);
let dht_key_string = String::from(&dht_key); let dht_key_string = String::from(&dht_key);
@ -150,50 +150,49 @@ pub async fn test_key_conversions(vcrypto: CryptoSystemVersion) {
assert_ne!(dht_key_secret2_string, dht_key2_string); assert_ne!(dht_key_secret2_string, dht_key2_string);
// Assert they convert back correctly // Assert they convert back correctly
let dht_key_back = key::DHTKey::try_from(dht_key_string.as_str()).unwrap(); let dht_key_back = PublicKey::try_from(dht_key_string.as_str()).unwrap();
let dht_key_back2 = key::DHTKey::try_from(dht_key_string2.as_str()).unwrap(); let dht_key_back2 = PublicKey::try_from(dht_key_string2.as_str()).unwrap();
assert_eq!(dht_key_back, dht_key_back2); assert_eq!(dht_key_back, dht_key_back2);
assert_eq!(dht_key_back, dht_key); assert_eq!(dht_key_back, dht_key);
assert_eq!(dht_key_back2, dht_key); assert_eq!(dht_key_back2, dht_key);
let dht_key_secret_back = key::DHTKeySecret::try_from(dht_key_secret_string.as_str()).unwrap(); let dht_key_secret_back = SecretKey::try_from(dht_key_secret_string.as_str()).unwrap();
assert_eq!(dht_key_secret_back, dht_key_secret); assert_eq!(dht_key_secret_back, dht_key_secret);
let dht_key2_back = key::DHTKey::try_from(dht_key2_string.as_str()).unwrap(); let dht_key2_back = PublicKey::try_from(dht_key2_string.as_str()).unwrap();
let dht_key2_back2 = key::DHTKey::try_from(dht_key2_string2.as_str()).unwrap(); let dht_key2_back2 = PublicKey::try_from(dht_key2_string2.as_str()).unwrap();
assert_eq!(dht_key2_back, dht_key2_back2); assert_eq!(dht_key2_back, dht_key2_back2);
assert_eq!(dht_key2_back, dht_key2); assert_eq!(dht_key2_back, dht_key2);
assert_eq!(dht_key2_back2, dht_key2); assert_eq!(dht_key2_back2, dht_key2);
let dht_key_secret2_back = let dht_key_secret2_back = SecretKey::try_from(dht_key_secret2_string.as_str()).unwrap();
key::DHTKeySecret::try_from(dht_key_secret2_string.as_str()).unwrap();
assert_eq!(dht_key_secret2_back, dht_key_secret2); assert_eq!(dht_key_secret2_back, dht_key_secret2);
// Assert string roundtrip // Assert string roundtrip
assert_eq!(String::from(&dht_key2_back), dht_key2_string); assert_eq!(String::from(&dht_key2_back), dht_key2_string);
// These conversions should fail // These conversions should fail
assert!(key::DHTKey::try_from("whatever").is_err()); assert!(PublicKey::try_from("whatever").is_err());
assert!(key::DHTKeySecret::try_from("whatever").is_err()); assert!(SecretKey::try_from("whatever").is_err());
assert!(key::DHTKey::try_from("").is_err()); assert!(PublicKey::try_from("").is_err());
assert!(key::DHTKeySecret::try_from("").is_err()); assert!(SecretKey::try_from("").is_err());
assert!(key::DHTKey::try_from(" ").is_err()); assert!(PublicKey::try_from(" ").is_err());
assert!(key::DHTKeySecret::try_from(" ").is_err()); assert!(SecretKey::try_from(" ").is_err());
assert!(key::DHTKey::try_from( assert!(PublicKey::try_from(
"qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq" "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"
) )
.is_err()); .is_err());
assert!(key::DHTKeySecret::try_from( assert!(SecretKey::try_from(
"qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq" "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"
) )
.is_err()); .is_err());
} }
pub async fn test_encode_decode(vcrypto: CryptoSystemVersion) { pub async fn test_encode_decode(vcrypto: CryptoSystemVersion) {
let dht_key = key::DHTKey::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").unwrap(); let dht_key = PublicKey::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").unwrap();
let dht_key_secret = let dht_key_secret =
key::DHTKeySecret::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").unwrap(); SecretKey::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").unwrap();
let dht_key_b = key::DHTKey::new(EMPTY_KEY); let dht_key_b = PublicKey::new(EMPTY_KEY);
let dht_key_secret_b = key::DHTKeySecret::new(EMPTY_KEY_SECRET); let dht_key_secret_b = SecretKey::new(EMPTY_KEY_SECRET);
assert_eq!(dht_key, dht_key_b); assert_eq!(dht_key, dht_key_b);
assert_eq!(dht_key_secret, dht_key_secret_b); assert_eq!(dht_key_secret, dht_key_secret_b);
@ -209,31 +208,31 @@ pub async fn test_encode_decode(vcrypto: CryptoSystemVersion) {
let e2s = dht_key_secret2.encode(); let e2s = dht_key_secret2.encode();
trace!("e2s: {:?}", e2s); trace!("e2s: {:?}", e2s);
let d1 = key::DHTKey::try_decode(e1.as_str()).unwrap(); let d1 = PublicKey::try_decode(e1.as_str()).unwrap();
trace!("d1: {:?}", d1); trace!("d1: {:?}", d1);
assert_eq!(dht_key, d1); assert_eq!(dht_key, d1);
let d1s = key::DHTKeySecret::try_decode(e1s.as_str()).unwrap(); let d1s = SecretKey::try_decode(e1s.as_str()).unwrap();
trace!("d1s: {:?}", d1s); trace!("d1s: {:?}", d1s);
assert_eq!(dht_key_secret, d1s); assert_eq!(dht_key_secret, d1s);
let d2 = key::DHTKey::try_decode(e2.as_str()).unwrap(); let d2 = PublicKey::try_decode(e2.as_str()).unwrap();
trace!("d2: {:?}", d2); trace!("d2: {:?}", d2);
assert_eq!(dht_key2, d2); assert_eq!(dht_key2, d2);
let d2s = key::DHTKeySecret::try_decode(e2s.as_str()).unwrap(); let d2s = SecretKey::try_decode(e2s.as_str()).unwrap();
trace!("d2s: {:?}", d2s); trace!("d2s: {:?}", d2s);
assert_eq!(dht_key_secret2, d2s); assert_eq!(dht_key_secret2, d2s);
// Failures // Failures
let f1 = key::DHTKeySecret::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); let f1 = SecretKey::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
assert!(f1.is_err()); assert!(f1.is_err());
let f2 = key::DHTKeySecret::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&"); let f2 = SecretKey::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&");
assert!(f2.is_err()); assert!(f2.is_err());
} }
async fn test_hash(vcrypto: CryptoSystemVersion) { async fn test_hash(vcrypto: CryptoSystemVersion) {
let mut s = BTreeSet::<key::DHTKey>::new(); let mut s = BTreeSet::<PublicKey>::new();
let k1 = vcrypto.generate_hash("abc".as_bytes()); let k1 = vcrypto.generate_hash("abc".as_bytes());
let k2 = vcrypto.generate_hash("abcd".as_bytes()); let k2 = vcrypto.generate_hash("abcd".as_bytes());
@ -333,7 +332,7 @@ pub async fn test_all() {
let crypto = api.crypto().unwrap(); let crypto = api.crypto().unwrap();
// Test versions // Test versions
for v in MIN_CRYPTO_VERSION..=MAX_CRYPTO_VERSION { for v in VALID_CRYPTO_KINDS {
let vcrypto = crypto.get(v).unwrap(); let vcrypto = crypto.get(v).unwrap();
test_generate_secret(vcrypto.clone()).await; test_generate_secret(vcrypto.clone()).await;

View File

@ -0,0 +1,233 @@
use super::*;
use core::cmp::{Eq, Ord, PartialEq, PartialOrd};
use core::convert::{TryFrom, TryInto};
use core::fmt;
use core::hash::Hash;
use rkyv::{Archive as RkyvArchive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
/// Cryptography version fourcc code
#[derive(
Copy,
Debug,
Default,
Clone,
Hash,
PartialOrd,
Ord,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes, PartialOrd, Ord, PartialEq, Eq))]
pub struct CryptoKind(pub [u8; 4]);
impl From<[u8; 4]> for CryptoKind {
fn from(b: [u8; 4]) -> Self {
Self(b)
}
}
impl TryFrom<&[u8]> for CryptoKind {
type Error = VeilidAPIError;
fn try_from(b: &[u8]) -> Result<Self, Self::Error> {
Ok(Self(b.try_into().map_err(VeilidAPIError::generic)?))
}
}
impl fmt::Display for CryptoKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{}", String::from_utf8_lossy(&self.0))
}
}
impl FromStr for CryptoKind {
type Err = VeilidAPIError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(
s.as_bytes().try_into().map_err(VeilidAPIError::generic)?,
))
}
}
#[derive(
Clone, Copy, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes))]
pub struct TypedKey {
pub kind: CryptoKind,
pub key: PublicKey,
}
impl TypedKey {
pub fn new(kind: CryptoKind, key: PublicKey) -> Self {
Self { kind, key }
}
}
impl fmt::Display for TypedKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{}:{}", self.kind, self.key.encode())
}
}
impl FromStr for TypedKey {
type Err = VeilidAPIError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let b = s.as_bytes();
if b.len() != (5 + PUBLIC_KEY_LENGTH_ENCODED) || b[4..5] != b":"[..] {
apibail_parse_error!("invalid typed key", s);
}
let kind: CryptoKind = b[0..4].try_into().expect("should not fail to convert");
let key = PublicKey::try_decode_bytes(&b[5..])?;
Ok(Self { kind, key })
}
}
#[derive(
Clone, Copy, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes))]
pub struct TypedKeyPair {
pub kind: CryptoKind,
pub key: PublicKey,
pub secret: SecretKey,
}
impl TypedKeyPair {
pub fn new(kind: CryptoKind, key: PublicKey, secret: SecretKey) -> Self {
Self { kind, key, secret }
}
}
impl fmt::Display for TypedKeyPair {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(
f,
"{}:{}:{}",
self.kind,
self.key.encode(),
self.secret.encode()
)
}
}
impl FromStr for TypedKeyPair {
type Err = VeilidAPIError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let b = s.as_bytes();
if b.len() != (5 + PUBLIC_KEY_LENGTH_ENCODED + 1 + SECRET_KEY_LENGTH_ENCODED)
|| b[4..5] != b":"[..]
|| b[5 + PUBLIC_KEY_LENGTH_ENCODED..6 + PUBLIC_KEY_LENGTH_ENCODED] != b":"[..]
{
apibail_parse_error!("invalid typed key pair", s);
}
let kind: CryptoKind = b[0..4].try_into().expect("should not fail to convert");
let key = PublicKey::try_decode_bytes(&b[5..5 + PUBLIC_KEY_LENGTH_ENCODED])?;
let secret = SecretKey::try_decode_bytes(&b[5 + PUBLIC_KEY_LENGTH_ENCODED + 1..])?;
Ok(Self { kind, key, secret })
}
}
#[derive(
Clone, Copy, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes))]
pub struct TypedSignature {
pub kind: CryptoKind,
pub signature: Signature,
}
impl TypedSignature {
pub fn new(kind: CryptoKind, signature: Signature) -> Self {
Self { kind, signature }
}
pub fn from_keyed(tks: &TypedKeySignature) -> Self {
Self {
kind: tks.kind,
signature: tks.signature,
}
}
pub fn from_pair_sig(tkp: &TypedKeyPair, sig: Signature) -> Self {
Self {
kind: tkp.kind,
signature: sig,
}
}
}
impl fmt::Display for TypedSignature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{}:{}", self.kind, self.signature.encode())
}
}
impl FromStr for TypedSignature {
type Err = VeilidAPIError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let b = s.as_bytes();
if b.len() != (5 + SIGNATURE_LENGTH_ENCODED) || b[4..5] != b":"[..] {
apibail_parse_error!("invalid typed signature", s);
}
let kind: CryptoKind = b[0..4].try_into()?;
let signature = Signature::try_decode_bytes(&b[5..])?;
Ok(Self { kind, signature })
}
}
#[derive(
Clone, Copy, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes))]
pub struct TypedKeySignature {
pub kind: CryptoKind,
pub key: PublicKey,
pub signature: Signature,
}
impl TypedKeySignature {
pub fn new(kind: CryptoKind, key: PublicKey, signature: Signature) -> Self {
Self {
kind,
key,
signature,
}
}
pub fn as_typed_signature(&self) -> TypedSignature {
TypedSignature {
kind: self.kind,
signature: self.signature,
}
}
}
impl fmt::Display for TypedKeySignature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(
f,
"{}:{}:{}",
self.kind,
self.key.encode(),
self.signature.encode()
)
}
}
impl FromStr for TypedKeySignature {
type Err = VeilidAPIError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let b = s.as_bytes();
if b.len() != (5 + PUBLIC_KEY_LENGTH_ENCODED + 1 + SIGNATURE_LENGTH_ENCODED)
|| b[4] != b':'
|| b[5 + PUBLIC_KEY_LENGTH_ENCODED] != b':'
{
apibail_parse_error!("invalid typed key signature", s);
}
let kind: CryptoKind = b[0..4].try_into().expect("should not fail to convert");
let key = PublicKey::try_decode_bytes(&b[5..5 + PUBLIC_KEY_LENGTH_ENCODED])?;
let signature = Signature::try_decode_bytes(&b[5 + PUBLIC_KEY_LENGTH_ENCODED + 1..])?;
Ok(Self {
kind,
key,
signature,
})
}
}

View File

@ -1,7 +1,7 @@
pub mod blake3digest512; pub mod blake3digest512;
pub use blake3digest512::*; pub use blake3digest512::*;
pub use super::*; use super::*;
use chacha20::cipher::{KeyIvInit, StreamCipher}; use chacha20::cipher::{KeyIvInit, StreamCipher};
use chacha20::XChaCha20; use chacha20::XChaCha20;
@ -11,11 +11,10 @@ use core::convert::TryInto;
use curve25519_dalek as cd; use curve25519_dalek as cd;
use digest::Digest; use digest::Digest;
use ed25519_dalek as ed; use ed25519_dalek as ed;
use ed25519_dalek::{Keypair, PublicKey, Signature};
use x25519_dalek as xd; use x25519_dalek as xd;
const AEAD_OVERHEAD: usize = 16; const AEAD_OVERHEAD: usize = 16;
pub const CRYPTO_KIND_VLD0: CryptoKind = CryptoKind([b'V', b'L', b'D', b'0']);
fn ed25519_to_x25519_pk(key: &ed::PublicKey) -> Result<xd::PublicKey, VeilidAPIError> { fn ed25519_to_x25519_pk(key: &ed::PublicKey) -> Result<xd::PublicKey, VeilidAPIError> {
let bytes = key.to_bytes(); let bytes = key.to_bytes();
@ -35,80 +34,80 @@ fn ed25519_to_x25519_sk(key: &ed::SecretKey) -> Result<xd::StaticSecret, VeilidA
/// V1 CryptoSystem /// V1 CryptoSystem
#[derive(Clone)] #[derive(Clone)]
pub struct CryptoV0System { pub struct CryptoSystemVLD0 {
crypto: Crypto, crypto: Crypto,
} }
impl CryptoV0System { impl CryptoSystemVLD0 {
pub fn new(crypto: Crypto) -> Self { pub fn new(crypto: Crypto) -> Self {
Self { crypto } Self { crypto }
} }
} }
impl CryptoSystem for CryptoV0System { impl CryptoSystem for CryptoSystemVLD0 {
// Accessors // Accessors
fn version(&self) -> CryptoVersion { fn kind(&self) -> CryptoKind {
return 0u8; CRYPTO_KIND_VLD0
} }
fn crypto(&self) -> Crypto { fn crypto(&self) -> Crypto {
return self.crypto.clone(); self.crypto.clone()
} }
// Cached Operations // Cached Operations
fn cached_dh( fn cached_dh(
&self, &self,
key: &DHTKey, key: &PublicKey,
secret: &DHTKeySecret, secret: &SecretKey,
) -> Result<SharedSecret, VeilidAPIError> { ) -> Result<SharedSecret, VeilidAPIError> {
self.crypto self.crypto
.cached_dh_internal::<CryptoV0System>(self, key, secret) .cached_dh_internal::<CryptoSystemVLD0>(self, key, secret)
} }
// Generation // Generation
fn random_nonce(&self) -> Nonce { fn random_nonce(&self) -> Nonce {
let mut nonce = [0u8; 24]; let mut nonce = [0u8; 24];
random_bytes(&mut nonce).unwrap(); random_bytes(&mut nonce).unwrap();
nonce Nonce::new(nonce)
} }
fn random_shared_secret(&self) -> SharedSecret { fn random_shared_secret(&self) -> SharedSecret {
let mut s = [0u8; 32]; let mut s = [0u8; 32];
random_bytes(&mut s).unwrap(); random_bytes(&mut s).unwrap();
s SharedSecret::new(s)
} }
fn compute_dh( fn compute_dh(
&self, &self,
key: &DHTKey, key: &PublicKey,
secret: &DHTKeySecret, secret: &SecretKey,
) -> Result<SharedSecret, VeilidAPIError> { ) -> Result<SharedSecret, VeilidAPIError> {
let pk_ed = ed::PublicKey::from_bytes(&key.bytes).map_err(VeilidAPIError::internal)?; let pk_ed = ed::PublicKey::from_bytes(&key.bytes).map_err(VeilidAPIError::internal)?;
let pk_xd = ed25519_to_x25519_pk(&pk_ed)?; let pk_xd = ed25519_to_x25519_pk(&pk_ed)?;
let sk_ed = ed::SecretKey::from_bytes(&secret.bytes).map_err(VeilidAPIError::internal)?; let sk_ed = ed::SecretKey::from_bytes(&secret.bytes).map_err(VeilidAPIError::internal)?;
let sk_xd = ed25519_to_x25519_sk(&sk_ed)?; let sk_xd = ed25519_to_x25519_sk(&sk_ed)?;
Ok(sk_xd.diffie_hellman(&pk_xd).to_bytes()) Ok(SharedSecret::new(sk_xd.diffie_hellman(&pk_xd).to_bytes()))
} }
fn generate_keypair(&self) -> (DHTKey, DHTKeySecret) { fn generate_keypair(&self) -> (PublicKey, SecretKey) {
let mut csprng = VeilidRng {}; let mut csprng = VeilidRng {};
let keypair = Keypair::generate(&mut csprng); let keypair = ed::Keypair::generate(&mut csprng);
let dht_key = DHTKey::new(keypair.public.to_bytes()); let dht_key = PublicKey::new(keypair.public.to_bytes());
let dht_key_secret = DHTKeySecret::new(keypair.secret.to_bytes()); let dht_key_secret = SecretKey::new(keypair.secret.to_bytes());
(dht_key, dht_key_secret) (dht_key, dht_key_secret)
} }
fn generate_hash(&self, data: &[u8]) -> DHTKey { fn generate_hash(&self, data: &[u8]) -> PublicKey {
DHTKey::new(*blake3::hash(data).as_bytes()) PublicKey::new(*blake3::hash(data).as_bytes())
} }
fn generate_hash_reader( fn generate_hash_reader(
&self, &self,
reader: &mut dyn std::io::Read, reader: &mut dyn std::io::Read,
) -> Result<DHTKey, VeilidAPIError> { ) -> Result<PublicKey, VeilidAPIError> {
let mut hasher = blake3::Hasher::new(); let mut hasher = blake3::Hasher::new();
std::io::copy(reader, &mut hasher).map_err(VeilidAPIError::generic)?; std::io::copy(reader, &mut hasher).map_err(VeilidAPIError::generic)?;
Ok(DHTKey::new(*hasher.finalize().as_bytes())) Ok(PublicKey::new(*hasher.finalize().as_bytes()))
} }
// Validation // Validation
fn validate_keypair(&self, dht_key: &DHTKey, dht_key_secret: &DHTKeySecret) -> bool { fn validate_keypair(&self, dht_key: &PublicKey, dht_key_secret: &SecretKey) -> bool {
let data = vec![0u8; 512]; let data = vec![0u8; 512];
let sig = match self.sign(dht_key, dht_key_secret, &data) { let sig = match self.sign(dht_key, dht_key_secret, &data) {
Ok(s) => s, Ok(s) => s,
@ -118,7 +117,7 @@ impl CryptoSystem for CryptoV0System {
}; };
self.verify(dht_key, &data, &sig).is_ok() self.verify(dht_key, &data, &sig).is_ok()
} }
fn validate_hash(&self, data: &[u8], dht_key: &DHTKey) -> bool { fn validate_hash(&self, data: &[u8], dht_key: &PublicKey) -> bool {
let bytes = *blake3::hash(data).as_bytes(); let bytes = *blake3::hash(data).as_bytes();
bytes == dht_key.bytes bytes == dht_key.bytes
@ -126,7 +125,7 @@ impl CryptoSystem for CryptoV0System {
fn validate_hash_reader( fn validate_hash_reader(
&self, &self,
reader: &mut dyn std::io::Read, reader: &mut dyn std::io::Read,
dht_key: &DHTKey, dht_key: &PublicKey,
) -> Result<bool, VeilidAPIError> { ) -> Result<bool, VeilidAPIError> {
let mut hasher = blake3::Hasher::new(); let mut hasher = blake3::Hasher::new();
std::io::copy(reader, &mut hasher).map_err(VeilidAPIError::generic)?; std::io::copy(reader, &mut hasher).map_err(VeilidAPIError::generic)?;
@ -134,29 +133,29 @@ impl CryptoSystem for CryptoV0System {
Ok(bytes == dht_key.bytes) Ok(bytes == dht_key.bytes)
} }
// Distance Metric // Distance Metric
fn distance(&self, key1: &DHTKey, key2: &DHTKey) -> DHTKeyDistance { fn distance(&self, key1: &PublicKey, key2: &PublicKey) -> PublicKeyDistance {
let mut bytes = [0u8; DHT_KEY_LENGTH]; let mut bytes = [0u8; PUBLIC_KEY_LENGTH];
for (n, byte) in bytes.iter_mut().enumerate() { for (n, byte) in bytes.iter_mut().enumerate() {
*byte = key1.bytes[n] ^ key2.bytes[n]; *byte = key1.bytes[n] ^ key2.bytes[n];
} }
DHTKeyDistance::new(bytes) PublicKeyDistance::new(bytes)
} }
// Authentication // Authentication
fn sign( fn sign(
&self, &self,
dht_key: &DHTKey, dht_key: &PublicKey,
dht_key_secret: &DHTKeySecret, dht_key_secret: &SecretKey,
data: &[u8], data: &[u8],
) -> Result<DHTSignature, VeilidAPIError> { ) -> Result<Signature, VeilidAPIError> {
let mut kpb: [u8; DHT_KEY_SECRET_LENGTH + DHT_KEY_LENGTH] = let mut kpb: [u8; SECRET_KEY_LENGTH + PUBLIC_KEY_LENGTH] =
[0u8; DHT_KEY_SECRET_LENGTH + DHT_KEY_LENGTH]; [0u8; SECRET_KEY_LENGTH + PUBLIC_KEY_LENGTH];
kpb[..DHT_KEY_SECRET_LENGTH].copy_from_slice(&dht_key_secret.bytes); kpb[..SECRET_KEY_LENGTH].copy_from_slice(&dht_key_secret.bytes);
kpb[DHT_KEY_SECRET_LENGTH..].copy_from_slice(&dht_key.bytes); kpb[SECRET_KEY_LENGTH..].copy_from_slice(&dht_key.bytes);
let keypair = Keypair::from_bytes(&kpb) let keypair = ed::Keypair::from_bytes(&kpb)
.map_err(|e| VeilidAPIError::parse_error("Keypair is invalid", e))?; .map_err(|e| VeilidAPIError::parse_error("Keypair is invalid", e))?;
let mut dig = Blake3Digest512::new(); let mut dig = Blake3Digest512::new();
@ -166,18 +165,18 @@ impl CryptoSystem for CryptoV0System {
.sign_prehashed(dig, None) .sign_prehashed(dig, None)
.map_err(VeilidAPIError::internal)?; .map_err(VeilidAPIError::internal)?;
let dht_sig = DHTSignature::new(sig.to_bytes()); let dht_sig = Signature::new(sig.to_bytes());
Ok(dht_sig) Ok(dht_sig)
} }
fn verify( fn verify(
&self, &self,
dht_key: &DHTKey, dht_key: &PublicKey,
data: &[u8], data: &[u8],
signature: &DHTSignature, signature: &Signature,
) -> Result<(), VeilidAPIError> { ) -> Result<(), VeilidAPIError> {
let pk = PublicKey::from_bytes(&dht_key.bytes) let pk = ed::PublicKey::from_bytes(&dht_key.bytes)
.map_err(|e| VeilidAPIError::parse_error("Public key is invalid", e))?; .map_err(|e| VeilidAPIError::parse_error("Public key is invalid", e))?;
let sig = Signature::from_bytes(&signature.bytes) let sig = ed::Signature::from_bytes(&signature.bytes)
.map_err(|e| VeilidAPIError::parse_error("Signature is invalid", e))?; .map_err(|e| VeilidAPIError::parse_error("Signature is invalid", e))?;
let mut dig = Blake3Digest512::new(); let mut dig = Blake3Digest512::new();
@ -199,8 +198,8 @@ impl CryptoSystem for CryptoV0System {
shared_secret: &SharedSecret, shared_secret: &SharedSecret,
associated_data: Option<&[u8]>, associated_data: Option<&[u8]>,
) -> Result<(), VeilidAPIError> { ) -> Result<(), VeilidAPIError> {
let key = ch::Key::from(*shared_secret); let key = ch::Key::from(shared_secret.bytes);
let xnonce = ch::XNonce::from(*nonce); let xnonce = ch::XNonce::from(nonce.bytes);
let aead = ch::XChaCha20Poly1305::new(&key); let aead = ch::XChaCha20Poly1305::new(&key);
aead.decrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body) aead.decrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body)
.map_err(map_to_string) .map_err(map_to_string)
@ -228,8 +227,8 @@ impl CryptoSystem for CryptoV0System {
shared_secret: &SharedSecret, shared_secret: &SharedSecret,
associated_data: Option<&[u8]>, associated_data: Option<&[u8]>,
) -> Result<(), VeilidAPIError> { ) -> Result<(), VeilidAPIError> {
let key = ch::Key::from(*shared_secret); let key = ch::Key::from(shared_secret.bytes);
let xnonce = ch::XNonce::from(*nonce); let xnonce = ch::XNonce::from(nonce.bytes);
let aead = ch::XChaCha20Poly1305::new(&key); let aead = ch::XChaCha20Poly1305::new(&key);
aead.encrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body) aead.encrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body)
@ -258,7 +257,7 @@ impl CryptoSystem for CryptoV0System {
nonce: &Nonce, nonce: &Nonce,
shared_secret: &SharedSecret, shared_secret: &SharedSecret,
) { ) {
let mut cipher = XChaCha20::new(shared_secret.into(), nonce.into()); let mut cipher = XChaCha20::new(&shared_secret.bytes.into(), &nonce.bytes.into());
cipher.apply_keystream(body); cipher.apply_keystream(body);
} }
@ -269,7 +268,7 @@ impl CryptoSystem for CryptoV0System {
nonce: &Nonce, nonce: &Nonce,
shared_secret: &SharedSecret, shared_secret: &SharedSecret,
) { ) {
let mut cipher = XChaCha20::new(shared_secret.into(), nonce.into()); let mut cipher = XChaCha20::new(&shared_secret.bytes.into(), &nonce.bytes.into());
cipher.apply_keystream_b2b(in_buf, &mut out_buf).unwrap(); cipher.apply_keystream_b2b(in_buf, &mut out_buf).unwrap();
} }

View File

@ -113,28 +113,35 @@ impl ProtectedStore {
} }
#[instrument(level = "trace", skip(self, value), ret, err)] #[instrument(level = "trace", skip(self, value), ret, err)]
pub async fn save_user_secret_string(&self, key: &str, value: &str) -> EyreResult<bool> { pub async fn save_user_secret_string<K: AsRef<str> + fmt::Debug, V: AsRef<str> + fmt::Debug>(
&self,
key: K,
value: V,
) -> EyreResult<bool> {
let inner = self.inner.lock(); let inner = self.inner.lock();
inner inner
.keyring_manager .keyring_manager
.as_ref() .as_ref()
.ok_or_else(|| eyre!("Protected store not initialized"))? .ok_or_else(|| eyre!("Protected store not initialized"))?
.with_keyring(&self.service_name(), key, |kr| { .with_keyring(&self.service_name(), key.as_ref(), |kr| {
let existed = kr.get_value().is_ok(); let existed = kr.get_value().is_ok();
kr.set_value(value)?; kr.set_value(value.as_ref())?;
Ok(existed) Ok(existed)
}) })
.wrap_err("failed to save user secret") .wrap_err("failed to save user secret")
} }
#[instrument(level = "trace", skip(self), err)] #[instrument(level = "trace", skip(self), err)]
pub async fn load_user_secret_string(&self, key: &str) -> EyreResult<Option<String>> { pub async fn load_user_secret_string<K: AsRef<str> + fmt::Debug>(
&self,
key: K,
) -> EyreResult<Option<String>> {
let inner = self.inner.lock(); let inner = self.inner.lock();
match inner match inner
.keyring_manager .keyring_manager
.as_ref() .as_ref()
.ok_or_else(|| eyre!("Protected store not initialized"))? .ok_or_else(|| eyre!("Protected store not initialized"))?
.with_keyring(&self.service_name(), key, |kr| kr.get_value()) .with_keyring(&self.service_name(), key.as_ref(), |kr| kr.get_value())
{ {
Ok(v) => Ok(Some(v)), Ok(v) => Ok(Some(v)),
Err(KeyringError::NoPasswordFound) => Ok(None), Err(KeyringError::NoPasswordFound) => Ok(None),
@ -143,17 +150,19 @@ impl ProtectedStore {
} }
#[instrument(level = "trace", skip(self, value))] #[instrument(level = "trace", skip(self, value))]
pub async fn save_user_secret_rkyv<T>(&self, key: &str, value: &T) -> EyreResult<bool> pub async fn save_user_secret_rkyv<K, T>(&self, key: K, value: &T) -> EyreResult<bool>
where where
K: AsRef<str> + fmt::Debug,
T: RkyvSerialize<rkyv::ser::serializers::AllocSerializer<1024>>, T: RkyvSerialize<rkyv::ser::serializers::AllocSerializer<1024>>,
{ {
let v = to_rkyv(value)?; let v = to_rkyv(value)?;
self.save_user_secret(&key, &v).await self.save_user_secret(key, &v).await
} }
#[instrument(level = "trace", skip(self, value))] #[instrument(level = "trace", skip(self, value))]
pub async fn save_user_secret_json<T>(&self, key: &str, value: &T) -> EyreResult<bool> pub async fn save_user_secret_json<K, T>(&self, key: K, value: &T) -> EyreResult<bool>
where where
K: AsRef<str> + fmt::Debug,
T: serde::Serialize, T: serde::Serialize,
{ {
let v = serde_json::to_vec(value)?; let v = serde_json::to_vec(value)?;
@ -161,8 +170,9 @@ impl ProtectedStore {
} }
#[instrument(level = "trace", skip(self))] #[instrument(level = "trace", skip(self))]
pub async fn load_user_secret_rkyv<T>(&self, key: &str) -> EyreResult<Option<T>> pub async fn load_user_secret_rkyv<K, T>(&self, key: K) -> EyreResult<Option<T>>
where where
K: AsRef<str> + fmt::Debug,
T: RkyvArchive, T: RkyvArchive,
<T as RkyvArchive>::Archived: <T as RkyvArchive>::Archived:
for<'t> bytecheck::CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>, for<'t> bytecheck::CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
@ -182,8 +192,9 @@ impl ProtectedStore {
} }
#[instrument(level = "trace", skip(self))] #[instrument(level = "trace", skip(self))]
pub async fn load_user_secret_json<T>(&self, key: &str) -> EyreResult<Option<T>> pub async fn load_user_secret_json<K, T>(&self, key: K) -> EyreResult<Option<T>>
where where
K: AsRef<str> + fmt::Debug,
T: for<'de> serde::de::Deserialize<'de>, T: for<'de> serde::de::Deserialize<'de>,
{ {
let out = self.load_user_secret(key).await?; let out = self.load_user_secret(key).await?;
@ -199,7 +210,11 @@ impl ProtectedStore {
} }
#[instrument(level = "trace", skip(self, value), ret, err)] #[instrument(level = "trace", skip(self, value), ret, err)]
pub async fn save_user_secret(&self, key: &str, value: &[u8]) -> EyreResult<bool> { pub async fn save_user_secret<K: AsRef<str> + fmt::Debug>(
&self,
key: K,
value: &[u8],
) -> EyreResult<bool> {
let mut s = BASE64URL_NOPAD.encode(value); let mut s = BASE64URL_NOPAD.encode(value);
s.push('!'); s.push('!');
@ -207,7 +222,10 @@ impl ProtectedStore {
} }
#[instrument(level = "trace", skip(self), err)] #[instrument(level = "trace", skip(self), err)]
pub async fn load_user_secret(&self, key: &str) -> EyreResult<Option<Vec<u8>>> { pub async fn load_user_secret<K: AsRef<str> + fmt::Debug>(
&self,
key: K,
) -> EyreResult<Option<Vec<u8>>> {
let mut s = match self.load_user_secret_string(key).await? { let mut s = match self.load_user_secret_string(key).await? {
Some(s) => s, Some(s) => s,
None => { None => {
@ -238,13 +256,13 @@ impl ProtectedStore {
} }
#[instrument(level = "trace", skip(self), ret, err)] #[instrument(level = "trace", skip(self), ret, err)]
pub async fn remove_user_secret(&self, key: &str) -> EyreResult<bool> { pub async fn remove_user_secret<K: AsRef<str> + fmt::Debug>(&self, key: K) -> EyreResult<bool> {
let inner = self.inner.lock(); let inner = self.inner.lock();
match inner match inner
.keyring_manager .keyring_manager
.as_ref() .as_ref()
.ok_or_else(|| eyre!("Protected store not initialized"))? .ok_or_else(|| eyre!("Protected store not initialized"))?
.with_keyring(&self.service_name(), key, |kr| kr.delete_value()) .with_keyring(&self.service_name(), key.as_ref(), |kr| kr.delete_value())
{ {
Ok(_) => Ok(true), Ok(_) => Ok(true),
Err(KeyringError::NoPasswordFound) => Ok(false), Err(KeyringError::NoPasswordFound) => Ok(false),

View File

@ -50,7 +50,11 @@ impl ProtectedStore {
} }
//#[instrument(level = "trace", skip(self, value), ret, err)] //#[instrument(level = "trace", skip(self, value), ret, err)]
pub async fn save_user_secret_string(&self, key: &str, value: &str) -> EyreResult<bool> { pub async fn save_user_secret_string<K: AsRef<str> + fmt::Debug, V: AsRef<str> + fmt::Debug>(
&self,
key: K,
value: V,
) -> EyreResult<bool> {
if is_browser() { if is_browser() {
let win = match window() { let win = match window() {
Some(w) => w, Some(w) => w,
@ -70,7 +74,7 @@ impl ProtectedStore {
} }
}; };
let vkey = self.browser_key_name(key); let vkey = self.browser_key_name(key.as_ref());
let prev = match ls let prev = match ls
.get_item(&vkey) .get_item(&vkey)
@ -81,7 +85,7 @@ impl ProtectedStore {
None => false, None => false,
}; };
ls.set_item(&vkey, value) ls.set_item(&vkey, value.as_ref())
.map_err(map_jsvalue_error) .map_err(map_jsvalue_error)
.wrap_err("exception_thrown")?; .wrap_err("exception_thrown")?;
@ -92,7 +96,10 @@ impl ProtectedStore {
} }
#[instrument(level = "trace", skip(self), err)] #[instrument(level = "trace", skip(self), err)]
pub async fn load_user_secret_string(&self, key: &str) -> EyreResult<Option<String>> { pub async fn load_user_secret_string<K: AsRef<str> + fmt::Debug>(
&self,
key: K,
) -> EyreResult<Option<String>> {
if is_browser() { if is_browser() {
let win = match window() { let win = match window() {
Some(w) => w, Some(w) => w,
@ -112,7 +119,7 @@ impl ProtectedStore {
} }
}; };
let vkey = self.browser_key_name(key); let vkey = self.browser_key_name(key.as_ref());
ls.get_item(&vkey) ls.get_item(&vkey)
.map_err(map_jsvalue_error) .map_err(map_jsvalue_error)
@ -123,26 +130,29 @@ impl ProtectedStore {
} }
#[instrument(level = "trace", skip(self, value))] #[instrument(level = "trace", skip(self, value))]
pub async fn save_user_secret_rkyv<T>(&self, key: &str, value: &T) -> EyreResult<bool> pub async fn save_user_secret_rkyv<K, T>(&self, key: K, value: &T) -> EyreResult<bool>
where where
K: AsRef<str> + fmt::Debug,
T: RkyvSerialize<rkyv::ser::serializers::AllocSerializer<1024>>, T: RkyvSerialize<rkyv::ser::serializers::AllocSerializer<1024>>,
{ {
let v = to_rkyv(value)?; let v = to_rkyv(value)?;
self.save_user_secret(&key, &v).await self.save_user_secret(key, &v).await
} }
#[instrument(level = "trace", skip(self, value))] #[instrument(level = "trace", skip(self, value))]
pub async fn save_user_secret_json<T>(&self, key: &str, value: &T) -> EyreResult<bool> pub async fn save_user_secret_json<K, T>(&self, key: K, value: &T) -> EyreResult<bool>
where where
K: AsRef<str> + fmt::Debug,
T: serde::Serialize, T: serde::Serialize,
{ {
let v = serde_json::to_vec(value)?; let v = serde_json::to_vec(value)?;
self.save_user_secret(&key, &v).await self.save_user_secret(key, &v).await
} }
#[instrument(level = "trace", skip(self))] #[instrument(level = "trace", skip(self))]
pub async fn load_user_secret_rkyv<T>(&self, key: &str) -> EyreResult<Option<T>> pub async fn load_user_secret_rkyv<K, T>(&self, key: K) -> EyreResult<Option<T>>
where where
K: AsRef<str> + fmt::Debug,
T: RkyvArchive, T: RkyvArchive,
<T as RkyvArchive>::Archived: <T as RkyvArchive>::Archived:
for<'t> bytecheck::CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>, for<'t> bytecheck::CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
@ -162,8 +172,9 @@ impl ProtectedStore {
} }
#[instrument(level = "trace", skip(self))] #[instrument(level = "trace", skip(self))]
pub async fn load_user_secret_json<T>(&self, key: &str) -> EyreResult<Option<T>> pub async fn load_user_secret_json<K, T>(&self, key: K) -> EyreResult<Option<T>>
where where
K: AsRef<str> + fmt::Debug,
T: for<'de> serde::de::Deserialize<'de>, T: for<'de> serde::de::Deserialize<'de>,
{ {
let out = self.load_user_secret(key).await?; let out = self.load_user_secret(key).await?;
@ -179,7 +190,11 @@ impl ProtectedStore {
} }
#[instrument(level = "trace", skip(self, value), ret, err)] #[instrument(level = "trace", skip(self, value), ret, err)]
pub async fn save_user_secret(&self, key: &str, value: &[u8]) -> EyreResult<bool> { pub async fn save_user_secret<K: AsRef<str> + fmt::Debug>(
&self,
key: K,
value: &[u8],
) -> EyreResult<bool> {
let mut s = BASE64URL_NOPAD.encode(value); let mut s = BASE64URL_NOPAD.encode(value);
s.push('!'); s.push('!');
@ -187,7 +202,10 @@ impl ProtectedStore {
} }
#[instrument(level = "trace", skip(self), err)] #[instrument(level = "trace", skip(self), err)]
pub async fn load_user_secret(&self, key: &str) -> EyreResult<Option<Vec<u8>>> { pub async fn load_user_secret<K: AsRef<str> + fmt::Debug>(
&self,
key: K,
) -> EyreResult<Option<Vec<u8>>> {
let mut s = match self.load_user_secret_string(key).await? { let mut s = match self.load_user_secret_string(key).await? {
Some(s) => s, Some(s) => s,
None => { None => {
@ -218,7 +236,7 @@ impl ProtectedStore {
} }
#[instrument(level = "trace", skip(self), ret, err)] #[instrument(level = "trace", skip(self), ret, err)]
pub async fn remove_user_secret(&self, key: &str) -> EyreResult<bool> { pub async fn remove_user_secret<K: AsRef<str> + fmt::Debug>(&self, key: K) -> EyreResult<bool> {
if is_browser() { if is_browser() {
let win = match window() { let win = match window() {
Some(w) => w, Some(w) => w,
@ -238,7 +256,7 @@ impl ProtectedStore {
} }
}; };
let vkey = self.browser_key_name(key); let vkey = self.browser_key_name(key.as_ref());
match ls match ls
.get_item(&vkey) .get_item(&vkey)

View File

@ -134,7 +134,7 @@ struct PublicAddressCheckCacheKey(ProtocolType, AddressType);
// The mutable state of the network manager // The mutable state of the network manager
struct NetworkManagerInner { struct NetworkManagerInner {
stats: NetworkManagerStats, stats: NetworkManagerStats,
client_whitelist: LruCache<DHTKey, ClientWhitelistEntry>, client_whitelist: LruCache<PublicKey, ClientWhitelistEntry>,
public_address_check_cache: public_address_check_cache:
BTreeMap<PublicAddressCheckCacheKey, LruCache<IpAddr, SocketAddress>>, BTreeMap<PublicAddressCheckCacheKey, LruCache<IpAddr, SocketAddress>>,
public_address_inconsistencies_table: public_address_inconsistencies_table:
@ -396,7 +396,7 @@ impl NetworkManager {
debug!("finished network manager shutdown"); debug!("finished network manager shutdown");
} }
pub fn update_client_whitelist(&self, client: DHTKey) { pub fn update_client_whitelist(&self, client: PublicKey) {
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
match inner.client_whitelist.entry(client) { match inner.client_whitelist.entry(client) {
hashlink::lru_cache::Entry::Occupied(mut entry) => { hashlink::lru_cache::Entry::Occupied(mut entry) => {
@ -411,7 +411,7 @@ impl NetworkManager {
} }
#[instrument(level = "trace", skip(self), ret)] #[instrument(level = "trace", skip(self), ret)]
pub fn check_client_whitelist(&self, client: DHTKey) -> bool { pub fn check_client_whitelist(&self, client: PublicKey) -> bool {
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
match inner.client_whitelist.entry(client) { match inner.client_whitelist.entry(client) {
@ -624,7 +624,7 @@ impl NetworkManager {
pub async fn handle_private_receipt<R: AsRef<[u8]>>( pub async fn handle_private_receipt<R: AsRef<[u8]>>(
&self, &self,
receipt_data: R, receipt_data: R,
private_route: DHTKey, private_route: PublicKey,
) -> NetworkResult<()> { ) -> NetworkResult<()> {
let receipt_manager = self.receipt_manager(); let receipt_manager = self.receipt_manager();
@ -731,7 +731,7 @@ impl NetworkManager {
#[instrument(level = "trace", skip(self, body), err)] #[instrument(level = "trace", skip(self, body), err)]
fn build_envelope<B: AsRef<[u8]>>( fn build_envelope<B: AsRef<[u8]>>(
&self, &self,
dest_node_id: DHTKey, dest_node_id: PublicKey,
version: u8, version: u8,
body: B, body: B,
) -> EyreResult<Vec<u8>> { ) -> EyreResult<Vec<u8>> {
@ -759,7 +759,7 @@ impl NetworkManager {
pub async fn send_envelope<B: AsRef<[u8]>>( pub async fn send_envelope<B: AsRef<[u8]>>(
&self, &self,
node_ref: NodeRef, node_ref: NodeRef,
envelope_node_id: Option<DHTKey>, envelope_node_id: Option<PublicKey>,
body: B, body: B,
) -> EyreResult<NetworkResult<SendDataKind>> { ) -> EyreResult<NetworkResult<SendDataKind>> {
let via_node_id = node_ref.node_id(); let via_node_id = node_ref.node_id();

View File

@ -112,7 +112,7 @@ impl DiscoveryContext {
&self, &self,
protocol_type: ProtocolType, protocol_type: ProtocolType,
address_type: AddressType, address_type: AddressType,
ignore_node: Option<DHTKey>, ignore_node: Option<PublicKey>,
) -> Option<(SocketAddress, NodeRef)> { ) -> Option<(SocketAddress, NodeRef)> {
let node_count = { let node_count = {
let config = self.routing_table.network_manager().config(); let config = self.routing_table.network_manager().config();
@ -130,7 +130,7 @@ impl DiscoveryContext {
dial_info_filter.clone(), dial_info_filter.clone(),
); );
let disallow_relays_filter = Box::new( let disallow_relays_filter = Box::new(
move |rti: &RoutingTableInner, _k: DHTKey, v: Option<Arc<BucketEntry>>| { move |rti: &RoutingTableInner, _k: PublicKey, v: Option<Arc<BucketEntry>>| {
let v = v.unwrap(); let v = v.unwrap();
v.with(rti, |_rti, e| { v.with(rti, |_rti, e| {
if let Some(n) = e.signed_node_info(RoutingDomain::PublicInternet) { if let Some(n) = e.signed_node_info(RoutingDomain::PublicInternet) {

View File

@ -11,7 +11,7 @@ pub enum ReceiptEvent {
ReturnedOutOfBand, ReturnedOutOfBand,
ReturnedInBand { inbound_noderef: NodeRef }, ReturnedInBand { inbound_noderef: NodeRef },
ReturnedSafety, ReturnedSafety,
ReturnedPrivate { private_route: DHTKey }, ReturnedPrivate { private_route: PublicKey },
Expired, Expired,
Cancelled, Cancelled,
} }
@ -21,7 +21,7 @@ pub enum ReceiptReturned {
OutOfBand, OutOfBand,
InBand { inbound_noderef: NodeRef }, InBand { inbound_noderef: NodeRef },
Safety, Safety,
Private { private_route: DHTKey }, Private { private_route: PublicKey },
} }
pub trait ReceiptCallback: Send + 'static { pub trait ReceiptCallback: Send + 'static {
@ -149,7 +149,7 @@ impl PartialOrd for ReceiptRecordTimestampSort {
pub struct ReceiptManagerInner { pub struct ReceiptManagerInner {
network_manager: NetworkManager, network_manager: NetworkManager,
records_by_nonce: BTreeMap<ReceiptNonce, Arc<Mutex<ReceiptRecord>>>, records_by_nonce: BTreeMap<Nonce, Arc<Mutex<ReceiptRecord>>>,
next_oldest_ts: Option<Timestamp>, next_oldest_ts: Option<Timestamp>,
stop_source: Option<StopSource>, stop_source: Option<StopSource>,
timeout_task: MustJoinSingleFuture<()>, timeout_task: MustJoinSingleFuture<()>,
@ -370,7 +370,7 @@ impl ReceiptManager {
inner.next_oldest_ts = new_next_oldest_ts; inner.next_oldest_ts = new_next_oldest_ts;
} }
pub async fn cancel_receipt(&self, nonce: &ReceiptNonce) -> EyreResult<()> { pub async fn cancel_receipt(&self, nonce: &Nonce) -> EyreResult<()> {
log_rpc!(debug "== Cancel Receipt {}", nonce.encode()); log_rpc!(debug "== Cancel Receipt {}", nonce.encode());
// Remove the record // Remove the record

View File

@ -4,15 +4,16 @@ use rkyv::{Archive as RkyvArchive, Deserialize as RkyvDeserialize, Serialize as
pub struct Bucket { pub struct Bucket {
routing_table: RoutingTable, routing_table: RoutingTable,
entries: BTreeMap<DHTKey, Arc<BucketEntry>>, entries: BTreeMap<PublicKey, Arc<BucketEntry>>,
newest_entry: Option<DHTKey>, newest_entry: Option<PublicKey>,
} }
pub(super) type EntriesIter<'a> = alloc::collections::btree_map::Iter<'a, DHTKey, Arc<BucketEntry>>; pub(super) type EntriesIter<'a> =
alloc::collections::btree_map::Iter<'a, PublicKey, Arc<BucketEntry>>;
#[derive(Debug, RkyvArchive, RkyvSerialize, RkyvDeserialize)] #[derive(Debug, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
#[archive_attr(repr(C), derive(CheckBytes))] #[archive_attr(repr(C), derive(CheckBytes))]
struct BucketEntryData { struct BucketEntryData {
key: DHTKey, key: PublicKey,
value: Vec<u8>, value: Vec<u8>,
} }
@ -20,7 +21,7 @@ struct BucketEntryData {
#[archive_attr(repr(C), derive(CheckBytes))] #[archive_attr(repr(C), derive(CheckBytes))]
struct BucketData { struct BucketData {
entries: Vec<BucketEntryData>, entries: Vec<BucketEntryData>,
newest_entry: Option<DHTKey>, newest_entry: Option<PublicKey>,
} }
fn state_ordering(state: BucketEntryState) -> usize { fn state_ordering(state: BucketEntryState) -> usize {
@ -70,7 +71,7 @@ impl Bucket {
Ok(out) Ok(out)
} }
pub(super) fn add_entry(&mut self, node_id: DHTKey) -> NodeRef { pub(super) fn add_entry(&mut self, node_id: PublicKey) -> NodeRef {
log_rtab!("Node added: {}", node_id.encode()); log_rtab!("Node added: {}", node_id.encode());
// Add new entry // Add new entry
@ -84,7 +85,7 @@ impl Bucket {
NodeRef::new(self.routing_table.clone(), node_id, entry, None) NodeRef::new(self.routing_table.clone(), node_id, entry, None)
} }
pub(super) fn remove_entry(&mut self, node_id: &DHTKey) { pub(super) fn remove_entry(&mut self, node_id: &PublicKey) {
log_rtab!("Node removed: {}", node_id); log_rtab!("Node removed: {}", node_id);
// Remove the entry // Remove the entry
@ -93,7 +94,7 @@ impl Bucket {
// newest_entry is updated by kick_bucket() // newest_entry is updated by kick_bucket()
} }
pub(super) fn entry(&self, key: &DHTKey) -> Option<Arc<BucketEntry>> { pub(super) fn entry(&self, key: &PublicKey) -> Option<Arc<BucketEntry>> {
self.entries.get(key).cloned() self.entries.get(key).cloned()
} }
@ -101,7 +102,7 @@ impl Bucket {
self.entries.iter() self.entries.iter()
} }
pub(super) fn kick(&mut self, bucket_depth: usize) -> Option<BTreeSet<DHTKey>> { pub(super) fn kick(&mut self, bucket_depth: usize) -> Option<BTreeSet<PublicKey>> {
// Get number of entries to attempt to purge from bucket // Get number of entries to attempt to purge from bucket
let bucket_len = self.entries.len(); let bucket_len = self.entries.len();
@ -111,11 +112,11 @@ impl Bucket {
} }
// Try to purge the newest entries that overflow the bucket // Try to purge the newest entries that overflow the bucket
let mut dead_node_ids: BTreeSet<DHTKey> = BTreeSet::new(); let mut dead_node_ids: BTreeSet<PublicKey> = BTreeSet::new();
let mut extra_entries = bucket_len - bucket_depth; let mut extra_entries = bucket_len - bucket_depth;
// Get the sorted list of entries by their kick order // Get the sorted list of entries by their kick order
let mut sorted_entries: Vec<(DHTKey, Arc<BucketEntry>)> = self let mut sorted_entries: Vec<(PublicKey, Arc<BucketEntry>)> = self
.entries .entries
.iter() .iter()
.map(|(k, v)| (k.clone(), v.clone())) .map(|(k, v)| (k.clone(), v.clone()))

View File

@ -310,7 +310,7 @@ impl BucketEntryInner {
opt_current_sni.as_ref().map(|s| s.as_ref()) opt_current_sni.as_ref().map(|s| s.as_ref())
} }
pub fn make_peer_info(&self, key: DHTKey, routing_domain: RoutingDomain) -> Option<PeerInfo> { pub fn make_peer_info(&self, key: PublicKey, routing_domain: RoutingDomain) -> Option<PeerInfo> {
let opt_current_sni = match routing_domain { let opt_current_sni = match routing_domain {
RoutingDomain::LocalNetwork => &self.local_network.signed_node_info, RoutingDomain::LocalNetwork => &self.local_network.signed_node_info,
RoutingDomain::PublicInternet => &self.public_internet.signed_node_info, RoutingDomain::PublicInternet => &self.public_internet.signed_node_info,

View File

@ -113,7 +113,7 @@ impl RoutingTable {
let mut cnt = 0; let mut cnt = 0;
out += &format!("Entries: {}\n", inner.bucket_entry_count); out += &format!("Entries: {}\n", inner.bucket_entry_count);
while b < blen { while b < blen {
let filtered_entries: Vec<(&DHTKey, &Arc<BucketEntry>)> = inner.buckets[b] let filtered_entries: Vec<(&PublicKey, &Arc<BucketEntry>)> = inner.buckets[b]
.entries() .entries()
.filter(|e| { .filter(|e| {
let state = e.1.with(inner, |_rti, e| e.state(cur_ts)); let state = e.1.with(inner, |_rti, e| e.state(cur_ts));
@ -149,7 +149,7 @@ impl RoutingTable {
out out
} }
pub(crate) fn debug_info_entry(&self, node_id: DHTKey) -> String { pub(crate) fn debug_info_entry(&self, node_id: PublicKey) -> String {
let mut out = String::new(); let mut out = String::new();
out += &format!("Entry {:?}:\n", node_id); out += &format!("Entry {:?}:\n", node_id);
if let Some(nr) = self.lookup_node_ref(node_id) { if let Some(nr) = self.lookup_node_ref(node_id) {

View File

@ -49,7 +49,7 @@ pub struct LowLevelPortInfo {
pub protocol_to_port: ProtocolToPortMapping, pub protocol_to_port: ProtocolToPortMapping,
} }
pub type RoutingTableEntryFilter<'t> = pub type RoutingTableEntryFilter<'t> =
Box<dyn FnMut(&RoutingTableInner, DHTKey, Option<Arc<BucketEntry>>) -> bool + Send + 't>; Box<dyn FnMut(&RoutingTableInner, PublicKey, Option<Arc<BucketEntry>>) -> bool + Send + 't>;
#[derive(Clone, Debug, Default, Eq, PartialEq)] #[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct RoutingTableHealth { pub struct RoutingTableHealth {
@ -71,9 +71,9 @@ pub(super) struct RoutingTableUnlockedInner {
network_manager: NetworkManager, network_manager: NetworkManager,
/// The current node's public DHT key /// The current node's public DHT key
node_id: DHTKey, node_id: PublicKey,
/// The current node's DHT key secret /// The current node's DHT key secret
node_id_secret: DHTKeySecret, node_id_secret: SecretKey,
/// Buckets to kick on our next kick task /// Buckets to kick on our next kick task
kick_queue: Mutex<BTreeSet<usize>>, kick_queue: Mutex<BTreeSet<usize>>,
/// Background process for computing statistics /// Background process for computing statistics
@ -149,11 +149,11 @@ impl RoutingTable {
f(&*self.unlocked_inner.config.get()) f(&*self.unlocked_inner.config.get())
} }
pub fn node_id(&self) -> DHTKey { pub fn node_id(&self) -> PublicKey {
self.unlocked_inner.node_id self.unlocked_inner.node_id
} }
pub fn node_id_secret(&self) -> DHTKeySecret { pub fn node_id_secret(&self) -> SecretKey {
self.unlocked_inner.node_id_secret self.unlocked_inner.node_id_secret
} }
@ -453,7 +453,7 @@ impl RoutingTable {
self.inner.write().purge_last_connections(); self.inner.write().purge_last_connections();
} }
fn find_bucket_index(&self, node_id: DHTKey) -> usize { fn find_bucket_index(&self, node_id: PublicKey) -> usize {
distance(&node_id, &self.unlocked_inner.node_id) distance(&node_id, &self.unlocked_inner.node_id)
.first_nonzero_bit() .first_nonzero_bit()
.unwrap() .unwrap()
@ -484,7 +484,7 @@ impl RoutingTable {
inner.get_all_nodes(self.clone(), cur_ts) inner.get_all_nodes(self.clone(), cur_ts)
} }
fn queue_bucket_kick(&self, node_id: DHTKey) { fn queue_bucket_kick(&self, node_id: PublicKey) {
let idx = self.find_bucket_index(node_id); let idx = self.find_bucket_index(node_id);
self.unlocked_inner.kick_queue.lock().insert(idx); self.unlocked_inner.kick_queue.lock().insert(idx);
} }
@ -492,7 +492,7 @@ impl RoutingTable {
/// Create a node reference, possibly creating a bucket entry /// Create a node reference, possibly creating a bucket entry
/// the 'update_func' closure is called on the node, and, if created, /// the 'update_func' closure is called on the node, and, if created,
/// in a locked fashion as to ensure the bucket entry state is always valid /// in a locked fashion as to ensure the bucket entry state is always valid
pub fn create_node_ref<F>(&self, node_id: DHTKey, update_func: F) -> Option<NodeRef> pub fn create_node_ref<F>(&self, node_id: PublicKey, update_func: F) -> Option<NodeRef>
where where
F: FnOnce(&mut RoutingTableInner, &mut BucketEntryInner), F: FnOnce(&mut RoutingTableInner, &mut BucketEntryInner),
{ {
@ -502,14 +502,14 @@ impl RoutingTable {
} }
/// Resolve an existing routing table entry and return a reference to it /// Resolve an existing routing table entry and return a reference to it
pub fn lookup_node_ref(&self, node_id: DHTKey) -> Option<NodeRef> { pub fn lookup_node_ref(&self, node_id: PublicKey) -> Option<NodeRef> {
self.inner.read().lookup_node_ref(self.clone(), node_id) self.inner.read().lookup_node_ref(self.clone(), node_id)
} }
/// Resolve an existing routing table entry and return a filtered reference to it /// Resolve an existing routing table entry and return a filtered reference to it
pub fn lookup_and_filter_noderef( pub fn lookup_and_filter_noderef(
&self, &self,
node_id: DHTKey, node_id: PublicKey,
routing_domain_set: RoutingDomainSet, routing_domain_set: RoutingDomainSet,
dial_info_filter: DialInfoFilter, dial_info_filter: DialInfoFilter,
) -> Option<NodeRef> { ) -> Option<NodeRef> {
@ -527,7 +527,7 @@ impl RoutingTable {
pub fn register_node_with_signed_node_info( pub fn register_node_with_signed_node_info(
&self, &self,
routing_domain: RoutingDomain, routing_domain: RoutingDomain,
node_id: DHTKey, node_id: PublicKey,
signed_node_info: SignedNodeInfo, signed_node_info: SignedNodeInfo,
allow_invalid: bool, allow_invalid: bool,
) -> Option<NodeRef> { ) -> Option<NodeRef> {
@ -544,7 +544,7 @@ impl RoutingTable {
/// and add the last peer address we have for it, since that's pretty common /// and add the last peer address we have for it, since that's pretty common
pub fn register_node_with_existing_connection( pub fn register_node_with_existing_connection(
&self, &self,
node_id: DHTKey, node_id: PublicKey,
descriptor: ConnectionDescriptor, descriptor: ConnectionDescriptor,
timestamp: Timestamp, timestamp: Timestamp,
) -> Option<NodeRef> { ) -> Option<NodeRef> {
@ -563,7 +563,7 @@ impl RoutingTable {
self.inner.read().get_routing_table_health() self.inner.read().get_routing_table_health()
} }
pub fn get_recent_peers(&self) -> Vec<(DHTKey, RecentPeersEntry)> { pub fn get_recent_peers(&self) -> Vec<(PublicKey, RecentPeersEntry)> {
let mut recent_peers = Vec::new(); let mut recent_peers = Vec::new();
let mut dead_peers = Vec::new(); let mut dead_peers = Vec::new();
let mut out = Vec::new(); let mut out = Vec::new();
@ -602,7 +602,7 @@ impl RoutingTable {
out out
} }
pub fn touch_recent_peer(&self, node_id: DHTKey, last_connection: ConnectionDescriptor) { pub fn touch_recent_peer(&self, node_id: PublicKey, last_connection: ConnectionDescriptor) {
self.inner self.inner
.write() .write()
.touch_recent_peer(node_id, last_connection) .touch_recent_peer(node_id, last_connection)
@ -722,7 +722,7 @@ impl RoutingTable {
let mut nodes_proto_v6 = vec![0usize, 0usize, 0usize, 0usize]; let mut nodes_proto_v6 = vec![0usize, 0usize, 0usize, 0usize];
let filter = Box::new( let filter = Box::new(
move |rti: &RoutingTableInner, _k: DHTKey, v: Option<Arc<BucketEntry>>| { move |rti: &RoutingTableInner, _k: PublicKey, v: Option<Arc<BucketEntry>>| {
let entry = v.unwrap(); let entry = v.unwrap();
entry.with(rti, |_rti, e| { entry.with(rti, |_rti, e| {
// skip nodes on our local network here // skip nodes on our local network here
@ -769,7 +769,7 @@ impl RoutingTable {
self.find_fastest_nodes( self.find_fastest_nodes(
protocol_types_len * 2 * max_per_type, protocol_types_len * 2 * max_per_type,
filters, filters,
|_rti, k: DHTKey, v: Option<Arc<BucketEntry>>| { |_rti, k: PublicKey, v: Option<Arc<BucketEntry>>| {
NodeRef::new(self.clone(), k, v.unwrap().clone(), None) NodeRef::new(self.clone(), k, v.unwrap().clone(), None)
}, },
) )
@ -786,10 +786,10 @@ impl RoutingTable {
where where
C: for<'a, 'b> FnMut( C: for<'a, 'b> FnMut(
&'a RoutingTableInner, &'a RoutingTableInner,
&'b (DHTKey, Option<Arc<BucketEntry>>), &'b (PublicKey, Option<Arc<BucketEntry>>),
&'b (DHTKey, Option<Arc<BucketEntry>>), &'b (PublicKey, Option<Arc<BucketEntry>>),
) -> core::cmp::Ordering, ) -> core::cmp::Ordering,
T: for<'r> FnMut(&'r RoutingTableInner, DHTKey, Option<Arc<BucketEntry>>) -> O + Send, T: for<'r> FnMut(&'r RoutingTableInner, PublicKey, Option<Arc<BucketEntry>>) -> O + Send,
{ {
self.inner self.inner
.read() .read()
@ -803,7 +803,7 @@ impl RoutingTable {
transform: T, transform: T,
) -> Vec<O> ) -> Vec<O>
where where
T: for<'r> FnMut(&'r RoutingTableInner, DHTKey, Option<Arc<BucketEntry>>) -> O + Send, T: for<'r> FnMut(&'r RoutingTableInner, PublicKey, Option<Arc<BucketEntry>>) -> O + Send,
{ {
self.inner self.inner
.read() .read()
@ -812,12 +812,12 @@ impl RoutingTable {
pub fn find_closest_nodes<'a, T, O>( pub fn find_closest_nodes<'a, T, O>(
&self, &self,
node_id: DHTKey, node_id: PublicKey,
filters: VecDeque<RoutingTableEntryFilter>, filters: VecDeque<RoutingTableEntryFilter>,
transform: T, transform: T,
) -> Vec<O> ) -> Vec<O>
where where
T: for<'r> FnMut(&'r RoutingTableInner, DHTKey, Option<Arc<BucketEntry>>) -> O + Send, T: for<'r> FnMut(&'r RoutingTableInner, PublicKey, Option<Arc<BucketEntry>>) -> O + Send,
{ {
self.inner self.inner
.read() .read()
@ -860,7 +860,7 @@ impl RoutingTable {
pub async fn find_node( pub async fn find_node(
&self, &self,
node_ref: NodeRef, node_ref: NodeRef,
node_id: DHTKey, node_id: PublicKey,
) -> EyreResult<NetworkResult<Vec<NodeRef>>> { ) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
let rpc_processor = self.rpc_processor(); let rpc_processor = self.rpc_processor();
@ -986,7 +986,7 @@ impl RoutingTable {
// Go through all entries and find fastest entry that matches filter function // Go through all entries and find fastest entry that matches filter function
let inner = self.inner.read(); let inner = self.inner.read();
let inner = &*inner; let inner = &*inner;
let mut best_inbound_relay: Option<(DHTKey, Arc<BucketEntry>)> = None; let mut best_inbound_relay: Option<(PublicKey, Arc<BucketEntry>)> = None;
// Iterate all known nodes for candidates // Iterate all known nodes for candidates
inner.with_entries(cur_ts, BucketEntryState::Unreliable, |rti, k, v| { inner.with_entries(cur_ts, BucketEntryState::Unreliable, |rti, k, v| {

View File

@ -6,7 +6,7 @@ use alloc::fmt;
pub struct NodeRefBaseCommon { pub struct NodeRefBaseCommon {
routing_table: RoutingTable, routing_table: RoutingTable,
node_id: DHTKey, node_id: PublicKey,
entry: Arc<BucketEntry>, entry: Arc<BucketEntry>,
filter: Option<NodeRefFilter>, filter: Option<NodeRefFilter>,
sequencing: Sequencing, sequencing: Sequencing,
@ -99,7 +99,7 @@ pub trait NodeRefBase: Sized {
fn routing_table(&self) -> RoutingTable { fn routing_table(&self) -> RoutingTable {
self.common().routing_table.clone() self.common().routing_table.clone()
} }
fn node_id(&self) -> DHTKey { fn node_id(&self) -> PublicKey {
self.common().node_id self.common().node_id
} }
fn has_updated_since_last_network_change(&self) -> bool { fn has_updated_since_last_network_change(&self) -> bool {
@ -346,7 +346,7 @@ pub struct NodeRef {
impl NodeRef { impl NodeRef {
pub fn new( pub fn new(
routing_table: RoutingTable, routing_table: RoutingTable,
node_id: DHTKey, node_id: PublicKey,
entry: Arc<BucketEntry>, entry: Arc<BucketEntry>,
filter: Option<NodeRefFilter>, filter: Option<NodeRefFilter>,
) -> Self { ) -> Self {

View File

@ -57,14 +57,14 @@ pub enum PrivateRouteHops {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct PrivateRoute { pub struct PrivateRoute {
/// The public key used for the entire route /// The public key used for the entire route
pub public_key: DHTKey, pub public_key: PublicKey,
pub hop_count: u8, pub hop_count: u8,
pub hops: PrivateRouteHops, pub hops: PrivateRouteHops,
} }
impl PrivateRoute { impl PrivateRoute {
/// Empty private route is the form used when receiving the last hop /// Empty private route is the form used when receiving the last hop
pub fn new_empty(public_key: DHTKey) -> Self { pub fn new_empty(public_key: PublicKey) -> Self {
Self { Self {
public_key, public_key,
hop_count: 0, hop_count: 0,
@ -72,7 +72,7 @@ impl PrivateRoute {
} }
} }
/// Stub route is the form used when no privacy is required, but you need to specify the destination for a safety route /// Stub route is the form used when no privacy is required, but you need to specify the destination for a safety route
pub fn new_stub(public_key: DHTKey, node: RouteNode) -> Self { pub fn new_stub(public_key: PublicKey, node: RouteNode) -> Self {
Self { Self {
public_key, public_key,
hop_count: 1, hop_count: 1,
@ -117,7 +117,7 @@ impl PrivateRoute {
} }
} }
pub fn first_hop_node_id(&self) -> Option<DHTKey> { pub fn first_hop_node_id(&self) -> Option<PublicKey> {
let PrivateRouteHops::FirstHop(pr_first_hop) = &self.hops else { let PrivateRouteHops::FirstHop(pr_first_hop) = &self.hops else {
return None; return None;
}; };
@ -162,13 +162,13 @@ pub enum SafetyRouteHops {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct SafetyRoute { pub struct SafetyRoute {
pub public_key: DHTKey, pub public_key: PublicKey,
pub hop_count: u8, pub hop_count: u8,
pub hops: SafetyRouteHops, pub hops: SafetyRouteHops,
} }
impl SafetyRoute { impl SafetyRoute {
pub fn new_stub(public_key: DHTKey, private_route: PrivateRoute) -> Self { pub fn new_stub(public_key: PublicKey, private_route: PrivateRoute) -> Self {
// First hop should have already been popped off for stubbed safety routes since // First hop should have already been popped off for stubbed safety routes since
// we are sending directly to the first hop // we are sending directly to the first hop
assert!(matches!(private_route.hops, PrivateRouteHops::Data(_))); assert!(matches!(private_route.hops, PrivateRouteHops::Data(_)));

View File

@ -17,8 +17,8 @@ const COMPILED_ROUTE_CACHE_SIZE: usize = 256;
// Compiled route key for caching // Compiled route key for caching
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] #[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
struct CompiledRouteCacheKey { struct CompiledRouteCacheKey {
sr_pubkey: DHTKey, sr_pubkey: PublicKey,
pr_pubkey: DHTKey, pr_pubkey: PublicKey,
} }
/// Compiled route (safety route + private route) /// Compiled route (safety route + private route)
@ -27,7 +27,7 @@ pub struct CompiledRoute {
/// The safety route attached to the private route /// The safety route attached to the private route
pub safety_route: SafetyRoute, pub safety_route: SafetyRoute,
/// The secret used to encrypt the message payload /// The secret used to encrypt the message payload
pub secret: DHTKeySecret, pub secret: SecretKey,
/// The node ref to the first hop in the compiled route /// The node ref to the first hop in the compiled route
pub first_hop: NodeRef, pub first_hop: NodeRef,
} }
@ -35,8 +35,8 @@ pub struct CompiledRoute {
#[derive(Clone, Debug, RkyvArchive, RkyvSerialize, RkyvDeserialize)] #[derive(Clone, Debug, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
#[archive_attr(repr(C), derive(CheckBytes))] #[archive_attr(repr(C), derive(CheckBytes))]
pub struct KeyPair { pub struct KeyPair {
key: DHTKey, key: PublicKey,
secret: DHTKeySecret, secret: SecretKey,
} }
#[derive(Clone, Debug, Default, RkyvArchive, RkyvSerialize, RkyvDeserialize)] #[derive(Clone, Debug, Default, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
@ -172,9 +172,9 @@ impl RouteStats {
pub struct RouteSpecDetail { pub struct RouteSpecDetail {
/// Secret key /// Secret key
#[with(Skip)] #[with(Skip)]
secret_key: DHTKeySecret, secret_key: SecretKey,
/// Route hops /// Route hops
hops: Vec<DHTKey>, hops: Vec<PublicKey>,
/// Route noderefs /// Route noderefs
#[with(Skip)] #[with(Skip)]
hop_node_refs: Vec<NodeRef>, hop_node_refs: Vec<NodeRef>,
@ -206,7 +206,7 @@ impl RouteSpecDetail {
pub fn hop_count(&self) -> usize { pub fn hop_count(&self) -> usize {
self.hops.len() self.hops.len()
} }
pub fn get_secret_key(&self) -> DHTKeySecret { pub fn get_secret_key(&self) -> SecretKey {
self.secret_key self.secret_key
} }
pub fn get_stability(&self) -> Stability { pub fn get_stability(&self) -> Stability {
@ -228,7 +228,7 @@ impl RouteSpecDetail {
#[archive_attr(repr(C, align(8)), derive(CheckBytes))] #[archive_attr(repr(C, align(8)), derive(CheckBytes))]
pub struct RouteSpecStoreContent { pub struct RouteSpecStoreContent {
/// All of the routes we have allocated so far /// All of the routes we have allocated so far
details: HashMap<DHTKey, RouteSpecDetail>, details: HashMap<PublicKey, RouteSpecDetail>,
} }
/// What remote private routes have seen /// What remote private routes have seen
@ -257,19 +257,19 @@ impl RemotePrivateRouteInfo {
#[derive(Debug)] #[derive(Debug)]
pub struct RouteSpecStoreCache { pub struct RouteSpecStoreCache {
/// How many times nodes have been used /// How many times nodes have been used
used_nodes: HashMap<DHTKey, usize>, used_nodes: HashMap<PublicKey, usize>,
/// How many times nodes have been used at the terminal point of a route /// How many times nodes have been used at the terminal point of a route
used_end_nodes: HashMap<DHTKey, usize>, used_end_nodes: HashMap<PublicKey, usize>,
/// Route spec hop cache, used to quickly disqualify routes /// Route spec hop cache, used to quickly disqualify routes
hop_cache: HashSet<Vec<u8>>, hop_cache: HashSet<Vec<u8>>,
/// Has a remote private route responded to a question and when /// Has a remote private route responded to a question and when
remote_private_route_cache: LruCache<DHTKey, RemotePrivateRouteInfo>, remote_private_route_cache: LruCache<PublicKey, RemotePrivateRouteInfo>,
/// Compiled route cache /// Compiled route cache
compiled_route_cache: LruCache<CompiledRouteCacheKey, SafetyRoute>, compiled_route_cache: LruCache<CompiledRouteCacheKey, SafetyRoute>,
/// List of dead allocated routes /// List of dead allocated routes
dead_routes: Vec<DHTKey>, dead_routes: Vec<PublicKey>,
/// List of dead remote routes /// List of dead remote routes
dead_remote_routes: Vec<DHTKey>, dead_remote_routes: Vec<PublicKey>,
} }
impl Default for RouteSpecStoreCache { impl Default for RouteSpecStoreCache {
@ -319,8 +319,8 @@ pub struct RouteSpecStore {
unlocked_inner: Arc<RouteSpecStoreUnlockedInner>, unlocked_inner: Arc<RouteSpecStoreUnlockedInner>,
} }
fn route_hops_to_hop_cache(hops: &[DHTKey]) -> Vec<u8> { fn route_hops_to_hop_cache(hops: &[PublicKey]) -> Vec<u8> {
let mut cache: Vec<u8> = Vec::with_capacity(hops.len() * DHT_KEY_LENGTH); let mut cache: Vec<u8> = Vec::with_capacity(hops.len() * PUBLIC_KEY_LENGTH);
for hop in hops { for hop in hops {
cache.extend_from_slice(&hop.bytes); cache.extend_from_slice(&hop.bytes);
} }
@ -329,7 +329,7 @@ fn route_hops_to_hop_cache(hops: &[DHTKey]) -> Vec<u8> {
/// get the hop cache key for a particular route permutation /// get the hop cache key for a particular route permutation
fn route_permutation_to_hop_cache(nodes: &[PeerInfo], perm: &[usize]) -> Vec<u8> { fn route_permutation_to_hop_cache(nodes: &[PeerInfo], perm: &[usize]) -> Vec<u8> {
let mut cache: Vec<u8> = Vec::with_capacity(perm.len() * DHT_KEY_LENGTH); let mut cache: Vec<u8> = Vec::with_capacity(perm.len() * PUBLIC_KEY_LENGTH);
for n in perm { for n in perm {
cache.extend_from_slice(&nodes[*n].node_id.key.bytes) cache.extend_from_slice(&nodes[*n].node_id.key.bytes)
} }
@ -584,13 +584,13 @@ impl RouteSpecStore {
fn detail<'a>( fn detail<'a>(
inner: &'a RouteSpecStoreInner, inner: &'a RouteSpecStoreInner,
public_key: &DHTKey, public_key: &PublicKey,
) -> Option<&'a RouteSpecDetail> { ) -> Option<&'a RouteSpecDetail> {
inner.content.details.get(public_key) inner.content.details.get(public_key)
} }
fn detail_mut<'a>( fn detail_mut<'a>(
inner: &'a mut RouteSpecStoreInner, inner: &'a mut RouteSpecStoreInner,
public_key: &DHTKey, public_key: &PublicKey,
) -> Option<&'a mut RouteSpecDetail> { ) -> Option<&'a mut RouteSpecDetail> {
inner.content.details.get_mut(public_key) inner.content.details.get_mut(public_key)
} }
@ -616,8 +616,8 @@ impl RouteSpecStore {
sequencing: Sequencing, sequencing: Sequencing,
hop_count: usize, hop_count: usize,
directions: DirectionSet, directions: DirectionSet,
avoid_node_ids: &[DHTKey], avoid_node_ids: &[PublicKey],
) -> EyreResult<Option<DHTKey>> { ) -> EyreResult<Option<PublicKey>> {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
let routing_table = self.unlocked_inner.routing_table.clone(); let routing_table = self.unlocked_inner.routing_table.clone();
let rti = &mut *routing_table.inner.write(); let rti = &mut *routing_table.inner.write();
@ -642,8 +642,8 @@ impl RouteSpecStore {
sequencing: Sequencing, sequencing: Sequencing,
hop_count: usize, hop_count: usize,
directions: DirectionSet, directions: DirectionSet,
avoid_node_ids: &[DHTKey], avoid_node_ids: &[PublicKey],
) -> EyreResult<Option<DHTKey>> { ) -> EyreResult<Option<PublicKey>> {
use core::cmp::Ordering; use core::cmp::Ordering;
if hop_count < 1 { if hop_count < 1 {
@ -666,7 +666,7 @@ impl RouteSpecStore {
// Get list of all nodes, and sort them for selection // Get list of all nodes, and sort them for selection
let cur_ts = get_aligned_timestamp(); let cur_ts = get_aligned_timestamp();
let filter = Box::new( let filter = Box::new(
move |rti: &RoutingTableInner, k: DHTKey, v: Option<Arc<BucketEntry>>| -> bool { move |rti: &RoutingTableInner, k: PublicKey, v: Option<Arc<BucketEntry>>| -> bool {
// Exclude our own node from routes // Exclude our own node from routes
if v.is_none() { if v.is_none() {
return false; return false;
@ -735,8 +735,8 @@ impl RouteSpecStore {
) as RoutingTableEntryFilter; ) as RoutingTableEntryFilter;
let filters = VecDeque::from([filter]); let filters = VecDeque::from([filter]);
let compare = |rti: &RoutingTableInner, let compare = |rti: &RoutingTableInner,
v1: &(DHTKey, Option<Arc<BucketEntry>>), v1: &(PublicKey, Option<Arc<BucketEntry>>),
v2: &(DHTKey, Option<Arc<BucketEntry>>)| v2: &(PublicKey, Option<Arc<BucketEntry>>)|
-> Ordering { -> Ordering {
// deprioritize nodes that we have already used as end points // deprioritize nodes that we have already used as end points
let e1_used_end = inner let e1_used_end = inner
@ -808,7 +808,7 @@ impl RouteSpecStore {
cmpout cmpout
}; };
let transform = let transform =
|rti: &RoutingTableInner, k: DHTKey, v: Option<Arc<BucketEntry>>| -> PeerInfo { |rti: &RoutingTableInner, k: PublicKey, v: Option<Arc<BucketEntry>>| -> PeerInfo {
// Return the peerinfo for that key // Return the peerinfo for that key
v.unwrap().with(rti, |_rti, e| { v.unwrap().with(rti, |_rti, e| {
e.make_peer_info(k, RoutingDomain::PublicInternet.into()) e.make_peer_info(k, RoutingDomain::PublicInternet.into())
@ -842,7 +842,7 @@ impl RouteSpecStore {
} }
// Ensure the route doesn't contain both a node and its relay // Ensure the route doesn't contain both a node and its relay
let mut seen_nodes: HashSet<DHTKey> = HashSet::new(); let mut seen_nodes: HashSet<PublicKey> = HashSet::new();
for n in permutation { for n in permutation {
let node = nodes.get(*n).unwrap(); let node = nodes.get(*n).unwrap();
if !seen_nodes.insert(node.node_id.key) { if !seen_nodes.insert(node.node_id.key) {
@ -956,7 +956,7 @@ impl RouteSpecStore {
} }
// Got a unique route, lets build the detail, register it, and return it // Got a unique route, lets build the detail, register it, and return it
let hops: Vec<DHTKey> = route_nodes.iter().map(|v| nodes[*v].node_id.key).collect(); let hops: Vec<PublicKey> = route_nodes.iter().map(|v| nodes[*v].node_id.key).collect();
let hop_node_refs = hops let hop_node_refs = hops
.iter() .iter()
.map(|k| { .map(|k| {
@ -994,10 +994,10 @@ impl RouteSpecStore {
#[instrument(level = "trace", skip(self, data, callback), ret)] #[instrument(level = "trace", skip(self, data, callback), ret)]
pub fn with_signature_validated_route<F,R>( pub fn with_signature_validated_route<F,R>(
&self, &self,
public_key: &DHTKey, public_key: &PublicKey,
signatures: &[DHTSignature], signatures: &[Signature],
data: &[u8], data: &[u8],
last_hop_id: DHTKey, last_hop_id: PublicKey,
callback: F, callback: F,
) -> Option<R> ) -> Option<R>
where F: FnOnce(&RouteSpecDetail) -> R, where F: FnOnce(&RouteSpecDetail) -> R,
@ -1038,7 +1038,7 @@ impl RouteSpecStore {
} }
#[instrument(level = "trace", skip(self), ret, err)] #[instrument(level = "trace", skip(self), ret, err)]
async fn test_allocated_route(&self, key: &DHTKey) -> EyreResult<bool> { async fn test_allocated_route(&self, key: &PublicKey) -> EyreResult<bool> {
// Make loopback route to test with // Make loopback route to test with
let dest = { let dest = {
let private_route = self.assemble_private_route(key, None)?; let private_route = self.assemble_private_route(key, None)?;
@ -1081,7 +1081,7 @@ impl RouteSpecStore {
} }
#[instrument(level = "trace", skip(self), ret, err)] #[instrument(level = "trace", skip(self), ret, err)]
async fn test_remote_route(&self, key: &DHTKey) -> EyreResult<bool> { async fn test_remote_route(&self, key: &PublicKey) -> EyreResult<bool> {
// Make private route test // Make private route test
let dest = { let dest = {
// Get the route to test // Get the route to test
@ -1121,7 +1121,7 @@ impl RouteSpecStore {
/// Test an allocated route for continuity /// Test an allocated route for continuity
#[instrument(level = "trace", skip(self), ret, err)] #[instrument(level = "trace", skip(self), ret, err)]
pub async fn test_route(&self, key: &DHTKey) -> EyreResult<bool> { pub async fn test_route(&self, key: &PublicKey) -> EyreResult<bool> {
let is_remote = { let is_remote = {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
let cur_ts = get_aligned_timestamp(); let cur_ts = get_aligned_timestamp();
@ -1136,7 +1136,7 @@ impl RouteSpecStore {
/// Release an allocated route that is no longer in use /// Release an allocated route that is no longer in use
#[instrument(level = "trace", skip(self), ret)] #[instrument(level = "trace", skip(self), ret)]
fn release_allocated_route(&self, public_key: &DHTKey) -> bool { fn release_allocated_route(&self, public_key: &PublicKey) -> bool {
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
let Some(detail) = inner.content.details.remove(public_key) else { let Some(detail) = inner.content.details.remove(public_key) else {
return false; return false;
@ -1185,7 +1185,7 @@ impl RouteSpecStore {
/// Release an allocated or remote route that is no longer in use /// Release an allocated or remote route that is no longer in use
#[instrument(level = "trace", skip(self), ret)] #[instrument(level = "trace", skip(self), ret)]
pub fn release_route(&self, key: &DHTKey) -> bool { pub fn release_route(&self, key: &PublicKey) -> bool {
let is_remote = { let is_remote = {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
@ -1214,8 +1214,8 @@ impl RouteSpecStore {
stability: Stability, stability: Stability,
sequencing: Sequencing, sequencing: Sequencing,
directions: DirectionSet, directions: DirectionSet,
avoid_node_ids: &[DHTKey], avoid_node_ids: &[PublicKey],
) -> Option<DHTKey> { ) -> Option<PublicKey> {
let cur_ts = get_aligned_timestamp(); let cur_ts = get_aligned_timestamp();
let mut routes = Vec::new(); let mut routes = Vec::new();
@ -1266,7 +1266,7 @@ impl RouteSpecStore {
/// List all allocated routes /// List all allocated routes
pub fn list_allocated_routes<F, R>(&self, mut filter: F) -> Vec<R> pub fn list_allocated_routes<F, R>(&self, mut filter: F) -> Vec<R>
where where
F: FnMut(&DHTKey, &RouteSpecDetail) -> Option<R>, F: FnMut(&PublicKey, &RouteSpecDetail) -> Option<R>,
{ {
let inner = self.inner.lock(); let inner = self.inner.lock();
let mut out = Vec::with_capacity(inner.content.details.len()); let mut out = Vec::with_capacity(inner.content.details.len());
@ -1281,7 +1281,7 @@ impl RouteSpecStore {
/// List all allocated routes /// List all allocated routes
pub fn list_remote_routes<F, R>(&self, mut filter: F) -> Vec<R> pub fn list_remote_routes<F, R>(&self, mut filter: F) -> Vec<R>
where where
F: FnMut(&DHTKey, &RemotePrivateRouteInfo) -> Option<R>, F: FnMut(&PublicKey, &RemotePrivateRouteInfo) -> Option<R>,
{ {
let inner = self.inner.lock(); let inner = self.inner.lock();
let mut out = Vec::with_capacity(inner.cache.remote_private_route_cache.len()); let mut out = Vec::with_capacity(inner.cache.remote_private_route_cache.len());
@ -1294,7 +1294,7 @@ impl RouteSpecStore {
} }
/// Get the debug description of a route /// Get the debug description of a route
pub fn debug_route(&self, key: &DHTKey) -> Option<String> { pub fn debug_route(&self, key: &PublicKey) -> Option<String> {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
let cur_ts = get_aligned_timestamp(); let cur_ts = get_aligned_timestamp();
// If this is a remote route, print it // If this is a remote route, print it
@ -1310,7 +1310,7 @@ impl RouteSpecStore {
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Route cache // Route cache
fn add_to_compiled_route_cache(&self, inner: &mut RouteSpecStoreInner, pr_pubkey: DHTKey, safety_route: SafetyRoute) fn add_to_compiled_route_cache(&self, inner: &mut RouteSpecStoreInner, pr_pubkey: PublicKey, safety_route: SafetyRoute)
{ {
let key = CompiledRouteCacheKey { let key = CompiledRouteCacheKey {
sr_pubkey: safety_route.public_key, sr_pubkey: safety_route.public_key,
@ -1322,7 +1322,7 @@ impl RouteSpecStore {
} }
} }
fn lookup_compiled_route_cache(&self, inner: &mut RouteSpecStoreInner, sr_pubkey: DHTKey, pr_pubkey: DHTKey) -> Option<SafetyRoute> { fn lookup_compiled_route_cache(&self, inner: &mut RouteSpecStoreInner, sr_pubkey: PublicKey, pr_pubkey: PublicKey) -> Option<SafetyRoute> {
let key = CompiledRouteCacheKey { let key = CompiledRouteCacheKey {
sr_pubkey, sr_pubkey,
@ -1332,7 +1332,7 @@ impl RouteSpecStore {
inner.cache.compiled_route_cache.get(&key).cloned() inner.cache.compiled_route_cache.get(&key).cloned()
} }
fn invalidate_compiled_route_cache(&self, inner: &mut RouteSpecStoreInner, dead_key: &DHTKey) { fn invalidate_compiled_route_cache(&self, inner: &mut RouteSpecStoreInner, dead_key: &PublicKey) {
let mut dead_entries = Vec::new(); let mut dead_entries = Vec::new();
for (k, _v) in inner.cache.compiled_route_cache.iter() { for (k, _v) in inner.cache.compiled_route_cache.iter() {
if k.sr_pubkey == *dead_key || k.pr_pubkey == *dead_key { if k.sr_pubkey == *dead_key || k.pr_pubkey == *dead_key {
@ -1581,8 +1581,8 @@ impl RouteSpecStore {
rti: &RoutingTableInner, rti: &RoutingTableInner,
safety_spec: &SafetySpec, safety_spec: &SafetySpec,
direction: DirectionSet, direction: DirectionSet,
avoid_node_ids: &[DHTKey], avoid_node_ids: &[PublicKey],
) -> EyreResult<Option<DHTKey>> { ) -> EyreResult<Option<PublicKey>> {
// Ensure the total hop count isn't too long for our config // Ensure the total hop count isn't too long for our config
let max_route_hop_count = self.unlocked_inner.max_route_hop_count; let max_route_hop_count = self.unlocked_inner.max_route_hop_count;
if safety_spec.hop_count == 0 { if safety_spec.hop_count == 0 {
@ -1641,8 +1641,8 @@ impl RouteSpecStore {
pub fn get_private_route_for_safety_spec( pub fn get_private_route_for_safety_spec(
&self, &self,
safety_spec: &SafetySpec, safety_spec: &SafetySpec,
avoid_node_ids: &[DHTKey], avoid_node_ids: &[PublicKey],
) -> EyreResult<Option<DHTKey>> { ) -> EyreResult<Option<PublicKey>> {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
let routing_table = self.unlocked_inner.routing_table.clone(); let routing_table = self.unlocked_inner.routing_table.clone();
let rti = &*routing_table.inner.read(); let rti = &*routing_table.inner.read();
@ -1660,7 +1660,7 @@ impl RouteSpecStore {
#[instrument(level = "trace", skip(self), err)] #[instrument(level = "trace", skip(self), err)]
pub fn assemble_private_route( pub fn assemble_private_route(
&self, &self,
key: &DHTKey, key: &PublicKey,
optimized: Option<bool>, optimized: Option<bool>,
) -> EyreResult<PrivateRoute> { ) -> EyreResult<PrivateRoute> {
let inner = &*self.inner.lock(); let inner = &*self.inner.lock();
@ -1749,7 +1749,7 @@ impl RouteSpecStore {
/// Import a remote private route for compilation /// Import a remote private route for compilation
#[instrument(level = "trace", skip(self, blob), ret, err)] #[instrument(level = "trace", skip(self, blob), ret, err)]
pub fn import_remote_private_route(&self, blob: Vec<u8>) -> EyreResult<DHTKey> { pub fn import_remote_private_route(&self, blob: Vec<u8>) -> EyreResult<PublicKey> {
// decode the pr blob // decode the pr blob
let private_route = RouteSpecStore::blob_to_private_route(blob)?; let private_route = RouteSpecStore::blob_to_private_route(blob)?;
@ -1774,7 +1774,7 @@ impl RouteSpecStore {
/// Release a remote private route that is no longer in use /// Release a remote private route that is no longer in use
#[instrument(level = "trace", skip(self), ret)] #[instrument(level = "trace", skip(self), ret)]
fn release_remote_private_route(&self, key: &DHTKey) -> bool { fn release_remote_private_route(&self, key: &PublicKey) -> bool {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
if inner.cache.remote_private_route_cache.remove(key).is_some() { if inner.cache.remote_private_route_cache.remove(key).is_some() {
// Mark it as dead for the update // Mark it as dead for the update
@ -1786,7 +1786,7 @@ impl RouteSpecStore {
} }
/// Retrieve an imported remote private route by its public key /// Retrieve an imported remote private route by its public key
pub fn get_remote_private_route(&self, key: &DHTKey) -> Option<PrivateRoute> { pub fn get_remote_private_route(&self, key: &PublicKey) -> Option<PrivateRoute> {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
let cur_ts = get_aligned_timestamp(); let cur_ts = get_aligned_timestamp();
Self::with_get_remote_private_route(inner, cur_ts, key, |r| { Self::with_get_remote_private_route(inner, cur_ts, key, |r| {
@ -1795,7 +1795,7 @@ impl RouteSpecStore {
} }
/// Retrieve an imported remote private route by its public key but don't 'touch' it /// Retrieve an imported remote private route by its public key but don't 'touch' it
pub fn peek_remote_private_route(&self, key: &DHTKey) -> Option<PrivateRoute> { pub fn peek_remote_private_route(&self, key: &PublicKey) -> Option<PrivateRoute> {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
let cur_ts = get_aligned_timestamp(); let cur_ts = get_aligned_timestamp();
Self::with_peek_remote_private_route(inner, cur_ts, key, |r| { Self::with_peek_remote_private_route(inner, cur_ts, key, |r| {
@ -1856,7 +1856,7 @@ impl RouteSpecStore {
fn with_get_remote_private_route<F, R>( fn with_get_remote_private_route<F, R>(
inner: &mut RouteSpecStoreInner, inner: &mut RouteSpecStoreInner,
cur_ts: Timestamp, cur_ts: Timestamp,
key: &DHTKey, key: &PublicKey,
f: F, f: F,
) -> Option<R> ) -> Option<R>
where where
@ -1876,7 +1876,7 @@ impl RouteSpecStore {
fn with_peek_remote_private_route<F, R>( fn with_peek_remote_private_route<F, R>(
inner: &mut RouteSpecStoreInner, inner: &mut RouteSpecStoreInner,
cur_ts: Timestamp, cur_ts: Timestamp,
key: &DHTKey, key: &PublicKey,
f: F, f: F,
) -> Option<R> ) -> Option<R>
where where
@ -1898,7 +1898,7 @@ impl RouteSpecStore {
/// Check to see if this remote (not ours) private route has seen our current node info yet /// Check to see if this remote (not ours) private route has seen our current node info yet
/// This happens when you communicate with a private route without a safety route /// This happens when you communicate with a private route without a safety route
pub fn has_remote_private_route_seen_our_node_info(&self, key: &DHTKey) -> bool { pub fn has_remote_private_route_seen_our_node_info(&self, key: &PublicKey) -> bool {
let our_node_info_ts = { let our_node_info_ts = {
let rti = &*self.unlocked_inner.routing_table.inner.read(); let rti = &*self.unlocked_inner.routing_table.inner.read();
let Some(ts) = rti.get_own_node_info_ts(RoutingDomain::PublicInternet) else { let Some(ts) = rti.get_own_node_info_ts(RoutingDomain::PublicInternet) else {
@ -1930,7 +1930,7 @@ impl RouteSpecStore {
/// was that node that had the private route. /// was that node that had the private route.
pub fn mark_remote_private_route_seen_our_node_info( pub fn mark_remote_private_route_seen_our_node_info(
&self, &self,
key: &DHTKey, key: &PublicKey,
cur_ts: Timestamp, cur_ts: Timestamp,
) -> EyreResult<()> { ) -> EyreResult<()> {
let our_node_info_ts = { let our_node_info_ts = {
@ -1960,7 +1960,7 @@ impl RouteSpecStore {
} }
/// Get the route statistics for any route we know about, local or remote /// Get the route statistics for any route we know about, local or remote
pub fn with_route_stats<F, R>(&self, cur_ts: Timestamp, key: &DHTKey, f: F) -> Option<R> pub fn with_route_stats<F, R>(&self, cur_ts: Timestamp, key: &PublicKey, f: F) -> Option<R>
where where
F: FnOnce(&mut RouteStats) -> R, F: FnOnce(&mut RouteStats) -> R,
{ {
@ -2007,7 +2007,7 @@ impl RouteSpecStore {
/// Mark route as published /// Mark route as published
/// When first deserialized, routes must be re-published in order to ensure they remain /// When first deserialized, routes must be re-published in order to ensure they remain
/// in the RouteSpecStore. /// in the RouteSpecStore.
pub fn mark_route_published(&self, key: &DHTKey, published: bool) -> EyreResult<()> { pub fn mark_route_published(&self, key: &PublicKey, published: bool) -> EyreResult<()> {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
Self::detail_mut(inner, key) Self::detail_mut(inner, key)
.ok_or_else(|| eyre!("route does not exist"))? .ok_or_else(|| eyre!("route does not exist"))?

View File

@ -10,13 +10,13 @@ pub enum ContactMethod {
/// Contact the node directly /// Contact the node directly
Direct(DialInfo), Direct(DialInfo),
/// Request via signal the node connect back directly (relay, target) /// Request via signal the node connect back directly (relay, target)
SignalReverse(DHTKey, DHTKey), SignalReverse(PublicKey, PublicKey),
/// Request via signal the node negotiate a hole punch (relay, target_node) /// Request via signal the node negotiate a hole punch (relay, target_node)
SignalHolePunch(DHTKey, DHTKey), SignalHolePunch(PublicKey, PublicKey),
/// Must use an inbound relay to reach the node /// Must use an inbound relay to reach the node
InboundRelay(DHTKey), InboundRelay(PublicKey),
/// Must use outbound relay to reach the node /// Must use outbound relay to reach the node
OutboundRelay(DHTKey), OutboundRelay(PublicKey),
} }
#[derive(Debug)] #[derive(Debug)]
@ -131,7 +131,7 @@ impl RoutingDomainDetailCommon {
let signed_node_info = match relay_info { let signed_node_info = match relay_info {
Some((relay_id, relay_sdni)) => SignedNodeInfo::Relayed( Some((relay_id, relay_sdni)) => SignedNodeInfo::Relayed(
SignedRelayedNodeInfo::with_secret( SignedRelayedNodeInfo::make_signatures(
NodeId::new(rti.unlocked_inner.node_id), NodeId::new(rti.unlocked_inner.node_id),
node_info, node_info,
relay_id, relay_id,

View File

@ -28,7 +28,7 @@ pub struct RoutingTableInner {
/// Statistics about the total bandwidth to/from this node /// Statistics about the total bandwidth to/from this node
pub(super) self_transfer_stats: TransferStatsDownUp, pub(super) self_transfer_stats: TransferStatsDownUp,
/// Peers we have recently communicated with /// Peers we have recently communicated with
pub(super) recent_peers: LruCache<DHTKey, RecentPeersEntry>, pub(super) recent_peers: LruCache<PublicKey, RecentPeersEntry>,
/// Storage for private/safety RouteSpecs /// Storage for private/safety RouteSpecs
pub(super) route_spec_store: Option<RouteSpecStore>, pub(super) route_spec_store: Option<RouteSpecStore>,
} }
@ -56,11 +56,11 @@ impl RoutingTableInner {
self.network_manager().rpc_processor() self.network_manager().rpc_processor()
} }
pub fn node_id(&self) -> DHTKey { pub fn node_id(&self) -> PublicKey {
self.unlocked_inner.node_id self.unlocked_inner.node_id
} }
pub fn node_id_secret(&self) -> DHTKeySecret { pub fn node_id_secret(&self) -> SecretKey {
self.unlocked_inner.node_id_secret self.unlocked_inner.node_id_secret
} }
@ -326,8 +326,8 @@ impl RoutingTableInner {
pub fn init_buckets(&mut self, routing_table: RoutingTable) { pub fn init_buckets(&mut self, routing_table: RoutingTable) {
// Size the buckets (one per bit) // Size the buckets (one per bit)
self.buckets.clear(); self.buckets.clear();
self.buckets.reserve(DHT_KEY_LENGTH * 8); self.buckets.reserve(PUBLIC_KEY_LENGTH * 8);
for _ in 0..DHT_KEY_LENGTH * 8 { for _ in 0..PUBLIC_KEY_LENGTH * 8 {
let bucket = Bucket::new(routing_table.clone()); let bucket = Bucket::new(routing_table.clone());
self.buckets.push(bucket); self.buckets.push(bucket);
} }
@ -412,7 +412,7 @@ impl RoutingTableInner {
} }
} }
pub fn find_bucket_index(&self, node_id: DHTKey) -> usize { pub fn find_bucket_index(&self, node_id: PublicKey) -> usize {
distance(&node_id, &self.unlocked_inner.node_id) distance(&node_id, &self.unlocked_inner.node_id)
.first_nonzero_bit() .first_nonzero_bit()
.unwrap() .unwrap()
@ -436,7 +436,10 @@ impl RoutingTableInner {
count count
} }
pub fn with_entries<T, F: FnMut(&RoutingTableInner, DHTKey, Arc<BucketEntry>) -> Option<T>>( pub fn with_entries<
T,
F: FnMut(&RoutingTableInner, PublicKey, Arc<BucketEntry>) -> Option<T>,
>(
&self, &self,
cur_ts: Timestamp, cur_ts: Timestamp,
min_state: BucketEntryState, min_state: BucketEntryState,
@ -461,7 +464,7 @@ impl RoutingTableInner {
pub fn with_entries_mut< pub fn with_entries_mut<
T, T,
F: FnMut(&mut RoutingTableInner, DHTKey, Arc<BucketEntry>) -> Option<T>, F: FnMut(&mut RoutingTableInner, PublicKey, Arc<BucketEntry>) -> Option<T>,
>( >(
&mut self, &mut self,
cur_ts: Timestamp, cur_ts: Timestamp,
@ -544,7 +547,7 @@ impl RoutingTableInner {
pub fn create_node_ref<F>( pub fn create_node_ref<F>(
&mut self, &mut self,
outer_self: RoutingTable, outer_self: RoutingTable,
node_id: DHTKey, node_id: PublicKey,
update_func: F, update_func: F,
) -> Option<NodeRef> ) -> Option<NodeRef>
where where
@ -597,7 +600,7 @@ impl RoutingTableInner {
} }
/// Resolve an existing routing table entry and return a reference to it /// Resolve an existing routing table entry and return a reference to it
pub fn lookup_node_ref(&self, outer_self: RoutingTable, node_id: DHTKey) -> Option<NodeRef> { pub fn lookup_node_ref(&self, outer_self: RoutingTable, node_id: PublicKey) -> Option<NodeRef> {
if node_id == self.unlocked_inner.node_id { if node_id == self.unlocked_inner.node_id {
log_rtab!(error "can't look up own node id in routing table"); log_rtab!(error "can't look up own node id in routing table");
return None; return None;
@ -613,7 +616,7 @@ impl RoutingTableInner {
pub fn lookup_and_filter_noderef( pub fn lookup_and_filter_noderef(
&self, &self,
outer_self: RoutingTable, outer_self: RoutingTable,
node_id: DHTKey, node_id: PublicKey,
routing_domain_set: RoutingDomainSet, routing_domain_set: RoutingDomainSet,
dial_info_filter: DialInfoFilter, dial_info_filter: DialInfoFilter,
) -> Option<NodeRef> { ) -> Option<NodeRef> {
@ -628,7 +631,7 @@ impl RoutingTableInner {
} }
/// Resolve an existing routing table entry and call a function on its entry without using a noderef /// Resolve an existing routing table entry and call a function on its entry without using a noderef
pub fn with_node_entry<F, R>(&self, node_id: DHTKey, f: F) -> Option<R> pub fn with_node_entry<F, R>(&self, node_id: PublicKey, f: F) -> Option<R>
where where
F: FnOnce(Arc<BucketEntry>) -> R, F: FnOnce(Arc<BucketEntry>) -> R,
{ {
@ -651,7 +654,7 @@ impl RoutingTableInner {
&mut self, &mut self,
outer_self: RoutingTable, outer_self: RoutingTable,
routing_domain: RoutingDomain, routing_domain: RoutingDomain,
node_id: DHTKey, node_id: PublicKey,
signed_node_info: SignedNodeInfo, signed_node_info: SignedNodeInfo,
allow_invalid: bool, allow_invalid: bool,
) -> Option<NodeRef> { ) -> Option<NodeRef> {
@ -696,7 +699,7 @@ impl RoutingTableInner {
pub fn register_node_with_existing_connection( pub fn register_node_with_existing_connection(
&mut self, &mut self,
outer_self: RoutingTable, outer_self: RoutingTable,
node_id: DHTKey, node_id: PublicKey,
descriptor: ConnectionDescriptor, descriptor: ConnectionDescriptor,
timestamp: Timestamp, timestamp: Timestamp,
) -> Option<NodeRef> { ) -> Option<NodeRef> {
@ -757,7 +760,7 @@ impl RoutingTableInner {
} }
} }
pub fn touch_recent_peer(&mut self, node_id: DHTKey, last_connection: ConnectionDescriptor) { pub fn touch_recent_peer(&mut self, node_id: PublicKey, last_connection: ConnectionDescriptor) {
self.recent_peers self.recent_peers
.insert(node_id, RecentPeersEntry { last_connection }); .insert(node_id, RecentPeersEntry { last_connection });
} }
@ -773,7 +776,7 @@ impl RoutingTableInner {
mut filters: VecDeque<RoutingTableEntryFilter>, mut filters: VecDeque<RoutingTableEntryFilter>,
) -> Vec<NodeRef> { ) -> Vec<NodeRef> {
let public_node_filter = Box::new( let public_node_filter = Box::new(
|rti: &RoutingTableInner, _k: DHTKey, v: Option<Arc<BucketEntry>>| { |rti: &RoutingTableInner, _k: PublicKey, v: Option<Arc<BucketEntry>>| {
let entry = v.unwrap(); let entry = v.unwrap();
entry.with(rti, |_rti, e| { entry.with(rti, |_rti, e| {
// skip nodes on local network // skip nodes on local network
@ -793,7 +796,7 @@ impl RoutingTableInner {
self.find_fastest_nodes( self.find_fastest_nodes(
node_count, node_count,
filters, filters,
|_rti: &RoutingTableInner, k: DHTKey, v: Option<Arc<BucketEntry>>| { |_rti: &RoutingTableInner, k: PublicKey, v: Option<Arc<BucketEntry>>| {
NodeRef::new(outer_self.clone(), k, v.unwrap().clone(), None) NodeRef::new(outer_self.clone(), k, v.unwrap().clone(), None)
}, },
) )
@ -819,7 +822,7 @@ impl RoutingTableInner {
&self, &self,
routing_domain: RoutingDomain, routing_domain: RoutingDomain,
own_peer_info: &PeerInfo, own_peer_info: &PeerInfo,
k: DHTKey, k: PublicKey,
v: Option<Arc<BucketEntry>>, v: Option<Arc<BucketEntry>>,
) -> PeerInfo { ) -> PeerInfo {
match v { match v {
@ -839,14 +842,15 @@ impl RoutingTableInner {
where where
C: for<'a, 'b> FnMut( C: for<'a, 'b> FnMut(
&'a RoutingTableInner, &'a RoutingTableInner,
&'b (DHTKey, Option<Arc<BucketEntry>>), &'b (PublicKey, Option<Arc<BucketEntry>>),
&'b (DHTKey, Option<Arc<BucketEntry>>), &'b (PublicKey, Option<Arc<BucketEntry>>),
) -> core::cmp::Ordering, ) -> core::cmp::Ordering,
T: for<'r> FnMut(&'r RoutingTableInner, DHTKey, Option<Arc<BucketEntry>>) -> O, T: for<'r> FnMut(&'r RoutingTableInner, PublicKey, Option<Arc<BucketEntry>>) -> O,
{ {
// collect all the nodes for sorting // collect all the nodes for sorting
let mut nodes = let mut nodes = Vec::<(PublicKey, Option<Arc<BucketEntry>>)>::with_capacity(
Vec::<(DHTKey, Option<Arc<BucketEntry>>)>::with_capacity(self.bucket_entry_count + 1); self.bucket_entry_count + 1,
);
// add our own node (only one of there with the None entry) // add our own node (only one of there with the None entry)
let mut filtered = false; let mut filtered = false;
@ -893,13 +897,13 @@ impl RoutingTableInner {
transform: T, transform: T,
) -> Vec<O> ) -> Vec<O>
where where
T: for<'r> FnMut(&'r RoutingTableInner, DHTKey, Option<Arc<BucketEntry>>) -> O, T: for<'r> FnMut(&'r RoutingTableInner, PublicKey, Option<Arc<BucketEntry>>) -> O,
{ {
let cur_ts = get_aligned_timestamp(); let cur_ts = get_aligned_timestamp();
// Add filter to remove dead nodes always // Add filter to remove dead nodes always
let filter_dead = Box::new( let filter_dead = Box::new(
move |rti: &RoutingTableInner, _k: DHTKey, v: Option<Arc<BucketEntry>>| { move |rti: &RoutingTableInner, _k: PublicKey, v: Option<Arc<BucketEntry>>| {
if let Some(entry) = &v { if let Some(entry) = &v {
// always filter out dead nodes // always filter out dead nodes
if entry.with(rti, |_rti, e| e.state(cur_ts) == BucketEntryState::Dead) { if entry.with(rti, |_rti, e| e.state(cur_ts) == BucketEntryState::Dead) {
@ -917,8 +921,8 @@ impl RoutingTableInner {
// Fastest sort // Fastest sort
let sort = |rti: &RoutingTableInner, let sort = |rti: &RoutingTableInner,
(a_key, a_entry): &(DHTKey, Option<Arc<BucketEntry>>), (a_key, a_entry): &(PublicKey, Option<Arc<BucketEntry>>),
(b_key, b_entry): &(DHTKey, Option<Arc<BucketEntry>>)| { (b_key, b_entry): &(PublicKey, Option<Arc<BucketEntry>>)| {
// same nodes are always the same // same nodes are always the same
if a_key == b_key { if a_key == b_key {
return core::cmp::Ordering::Equal; return core::cmp::Ordering::Equal;
@ -973,12 +977,12 @@ impl RoutingTableInner {
pub fn find_closest_nodes<T, O>( pub fn find_closest_nodes<T, O>(
&self, &self,
node_id: DHTKey, node_id: PublicKey,
filters: VecDeque<RoutingTableEntryFilter>, filters: VecDeque<RoutingTableEntryFilter>,
transform: T, transform: T,
) -> Vec<O> ) -> Vec<O>
where where
T: for<'r> FnMut(&'r RoutingTableInner, DHTKey, Option<Arc<BucketEntry>>) -> O, T: for<'r> FnMut(&'r RoutingTableInner, PublicKey, Option<Arc<BucketEntry>>) -> O,
{ {
let cur_ts = get_aligned_timestamp(); let cur_ts = get_aligned_timestamp();
let node_count = { let node_count = {
@ -989,8 +993,8 @@ impl RoutingTableInner {
// closest sort // closest sort
let sort = |rti: &RoutingTableInner, let sort = |rti: &RoutingTableInner,
(a_key, a_entry): &(DHTKey, Option<Arc<BucketEntry>>), (a_key, a_entry): &(PublicKey, Option<Arc<BucketEntry>>),
(b_key, b_entry): &(DHTKey, Option<Arc<BucketEntry>>)| { (b_key, b_entry): &(PublicKey, Option<Arc<BucketEntry>>)| {
// same nodes are always the same // same nodes are always the same
if a_key == b_key { if a_key == b_key {
return core::cmp::Ordering::Equal; return core::cmp::Ordering::Equal;

View File

@ -11,7 +11,7 @@ pub struct BootstrapRecord {
max_version: u8, max_version: u8,
dial_info_details: Vec<DialInfoDetail>, dial_info_details: Vec<DialInfoDetail>,
} }
pub type BootstrapRecordMap = BTreeMap<DHTKey, BootstrapRecord>; pub type BootstrapRecordMap = BTreeMap<PublicKey, BootstrapRecord>;
impl RoutingTable { impl RoutingTable {
// Bootstrap lookup process // Bootstrap lookup process
@ -58,7 +58,7 @@ impl RoutingTable {
Ok(v) => v, Ok(v) => v,
}; };
// for each record resolve into key/bootstraprecord pairs // for each record resolve into key/bootstraprecord pairs
let mut bootstrap_records: Vec<(DHTKey, BootstrapRecord)> = Vec::new(); let mut bootstrap_records: Vec<(PublicKey, BootstrapRecord)> = Vec::new();
for bsnirecord in bsnirecords { for bsnirecord in bsnirecords {
// Bootstrap TXT Record Format Version 0: // Bootstrap TXT Record Format Version 0:
// txt_version,min_version,max_version,nodeid,hostname,dialinfoshort* // txt_version,min_version,max_version,nodeid,hostname,dialinfoshort*
@ -115,7 +115,7 @@ impl RoutingTable {
// Node Id // Node Id
let node_id_str = &records[3]; let node_id_str = &records[3];
let node_id_key = match DHTKey::try_decode(node_id_str) { let node_id_key = match PublicKey::try_decode(node_id_str) {
Ok(v) => v, Ok(v) => v,
Err(e) => { Err(e) => {
warn!( warn!(

View File

@ -24,7 +24,7 @@ impl RoutingTable {
let noderefs = routing_table.find_fastest_nodes( let noderefs = routing_table.find_fastest_nodes(
min_peer_count, min_peer_count,
VecDeque::new(), VecDeque::new(),
|_rti, k: DHTKey, v: Option<Arc<BucketEntry>>| { |_rti, k: PublicKey, v: Option<Arc<BucketEntry>>| {
NodeRef::new(routing_table.clone(), k, v.unwrap().clone(), None) NodeRef::new(routing_table.clone(), k, v.unwrap().clone(), None)
}, },
); );

View File

@ -8,7 +8,7 @@ const BACKGROUND_SAFETY_ROUTE_COUNT: usize = 2;
impl RoutingTable { impl RoutingTable {
/// Fastest routes sort /// Fastest routes sort
fn route_sort_latency_fn(a: &(DHTKey, u64), b: &(DHTKey, u64)) -> cmp::Ordering { fn route_sort_latency_fn(a: &(PublicKey, u64), b: &(PublicKey, u64)) -> cmp::Ordering {
let mut al = a.1; let mut al = a.1;
let mut bl = b.1; let mut bl = b.1;
// Treat zero latency as uncalculated // Treat zero latency as uncalculated
@ -35,14 +35,14 @@ impl RoutingTable {
/// ///
/// If a route doesn't 'need_testing', then we neither test nor drop it /// If a route doesn't 'need_testing', then we neither test nor drop it
#[instrument(level = "trace", skip(self))] #[instrument(level = "trace", skip(self))]
fn get_allocated_routes_to_test(&self, cur_ts: Timestamp) -> Vec<DHTKey> { fn get_allocated_routes_to_test(&self, cur_ts: Timestamp) -> Vec<PublicKey> {
let default_route_hop_count = let default_route_hop_count =
self.with_config(|c| c.network.rpc.default_route_hop_count as usize); self.with_config(|c| c.network.rpc.default_route_hop_count as usize);
let rss = self.route_spec_store(); let rss = self.route_spec_store();
let mut must_test_routes = Vec::<DHTKey>::new(); let mut must_test_routes = Vec::<PublicKey>::new();
let mut unpublished_routes = Vec::<(DHTKey, u64)>::new(); let mut unpublished_routes = Vec::<(PublicKey, u64)>::new();
let mut expired_routes = Vec::<DHTKey>::new(); let mut expired_routes = Vec::<PublicKey>::new();
rss.list_allocated_routes(|k, v| { rss.list_allocated_routes(|k, v| {
let stats = v.get_stats(); let stats = v.get_stats();
// Ignore nodes that don't need testing // Ignore nodes that don't need testing
@ -95,7 +95,7 @@ impl RoutingTable {
async fn test_route_set( async fn test_route_set(
&self, &self,
stop_token: StopToken, stop_token: StopToken,
routes_needing_testing: Vec<DHTKey>, routes_needing_testing: Vec<PublicKey>,
) -> EyreResult<()> { ) -> EyreResult<()> {
if routes_needing_testing.is_empty() { if routes_needing_testing.is_empty() {
return Ok(()); return Ok(());
@ -107,7 +107,7 @@ impl RoutingTable {
#[derive(Default, Debug)] #[derive(Default, Debug)]
struct TestRouteContext { struct TestRouteContext {
failed: bool, failed: bool,
dead_routes: Vec<DHTKey>, dead_routes: Vec<PublicKey>,
} }
let mut unord = FuturesUnordered::new(); let mut unord = FuturesUnordered::new();

View File

@ -1,7 +1,7 @@
use super::*; use super::*;
use core::convert::TryInto; use core::convert::TryInto;
pub fn decode_dht_key(public_key: &veilid_capnp::key256::Reader) -> DHTKey { pub fn decode_dht_key(public_key: &veilid_capnp::key256::Reader) -> PublicKey {
let u0 = public_key.get_u0().to_be_bytes(); let u0 = public_key.get_u0().to_be_bytes();
let u1 = public_key.get_u1().to_be_bytes(); let u1 = public_key.get_u1().to_be_bytes();
let u2 = public_key.get_u2().to_be_bytes(); let u2 = public_key.get_u2().to_be_bytes();
@ -13,11 +13,11 @@ pub fn decode_dht_key(public_key: &veilid_capnp::key256::Reader) -> DHTKey {
x[16..24].copy_from_slice(&u2); x[16..24].copy_from_slice(&u2);
x[24..32].copy_from_slice(&u3); x[24..32].copy_from_slice(&u3);
DHTKey::new(x) PublicKey::new(x)
} }
pub fn encode_dht_key( pub fn encode_dht_key(
key: &DHTKey, key: &PublicKey,
builder: &mut veilid_capnp::key256::Builder, builder: &mut veilid_capnp::key256::Builder,
) -> Result<(), RPCError> { ) -> Result<(), RPCError> {
builder.set_u0(u64::from_be_bytes( builder.set_u0(u64::from_be_bytes(

View File

@ -1,6 +1,6 @@
use super::*; use super::*;
pub fn encode_signature(sig: &DHTSignature, builder: &mut veilid_capnp::signature512::Builder) { pub fn encode_signature(sig: &Signature, builder: &mut veilid_capnp::signature512::Builder) {
let sig = &sig.bytes; let sig = &sig.bytes;
builder.set_u0(u64::from_be_bytes( builder.set_u0(u64::from_be_bytes(
@ -29,7 +29,7 @@ pub fn encode_signature(sig: &DHTSignature, builder: &mut veilid_capnp::signatur
)); ));
} }
pub fn decode_signature(reader: &veilid_capnp::signature512::Reader) -> DHTSignature { pub fn decode_signature(reader: &veilid_capnp::signature512::Reader) -> Signature {
let u0 = reader.get_u0().to_be_bytes(); let u0 = reader.get_u0().to_be_bytes();
let u1 = reader.get_u1().to_be_bytes(); let u1 = reader.get_u1().to_be_bytes();
let u2 = reader.get_u2().to_be_bytes(); let u2 = reader.get_u2().to_be_bytes();
@ -39,7 +39,7 @@ pub fn decode_signature(reader: &veilid_capnp::signature512::Reader) -> DHTSigna
let u6 = reader.get_u6().to_be_bytes(); let u6 = reader.get_u6().to_be_bytes();
let u7 = reader.get_u7().to_be_bytes(); let u7 = reader.get_u7().to_be_bytes();
DHTSignature::new([ Signature::new([
u0[0], u0[1], u0[2], u0[3], u0[4], u0[5], u0[6], u0[7], // u0 u0[0], u0[1], u0[2], u0[3], u0[4], u0[5], u0[6], u0[7], // u0
u1[0], u1[1], u1[2], u1[3], u1[4], u1[5], u1[6], u1[7], // u1 u1[0], u1[1], u1[2], u1[3], u1[4], u1[5], u1[6], u1[7], // u1
u2[0], u2[1], u2[2], u2[3], u2[4], u2[5], u2[6], u2[7], // u2 u2[0], u2[1], u2[2], u2[3], u2[4], u2[5], u2[6], u2[7], // u2

View File

@ -117,7 +117,7 @@ impl RPCOperation {
pub fn decode( pub fn decode(
operation_reader: &veilid_capnp::operation::Reader, operation_reader: &veilid_capnp::operation::Reader,
opt_sender_node_id: Option<&DHTKey>, opt_sender_node_id: Option<&PublicKey>,
) -> Result<Self, RPCError> { ) -> Result<Self, RPCError> {
let op_id = OperationId::new(operation_reader.get_op_id()); let op_id = OperationId::new(operation_reader.get_op_id());

View File

@ -2,7 +2,7 @@ use super::*;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RPCOperationFindBlockQ { pub struct RPCOperationFindBlockQ {
pub block_id: DHTKey, pub block_id: PublicKey,
} }
impl RPCOperationFindBlockQ { impl RPCOperationFindBlockQ {

View File

@ -2,7 +2,7 @@ use super::*;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RPCOperationFindNodeQ { pub struct RPCOperationFindNodeQ {
pub node_id: DHTKey, pub node_id: PublicKey,
} }
impl RPCOperationFindNodeQ { impl RPCOperationFindNodeQ {

View File

@ -2,17 +2,15 @@ use super::*;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RoutedOperation { pub struct RoutedOperation {
pub version: u8,
pub sequencing: Sequencing, pub sequencing: Sequencing,
pub signatures: Vec<DHTSignature>, pub signatures: Vec<TypedSignature>,
pub nonce: Nonce, pub nonce: Nonce,
pub data: Vec<u8>, pub data: Vec<u8>,
} }
impl RoutedOperation { impl RoutedOperation {
pub fn new(version: u8, sequencing: Sequencing, nonce: Nonce, data: Vec<u8>) -> Self { pub fn new(sequencing: Sequencing, nonce: Nonce, data: Vec<u8>) -> Self {
Self { Self {
version,
sequencing, sequencing,
signatures: Vec::new(), signatures: Vec::new(),
nonce, nonce,
@ -24,25 +22,23 @@ impl RoutedOperation {
reader: &veilid_capnp::routed_operation::Reader, reader: &veilid_capnp::routed_operation::Reader,
) -> Result<RoutedOperation, RPCError> { ) -> Result<RoutedOperation, RPCError> {
let sigs_reader = reader.get_signatures().map_err(RPCError::protocol)?; let sigs_reader = reader.get_signatures().map_err(RPCError::protocol)?;
let mut signatures = Vec::<DHTSignature>::with_capacity( let mut signatures = Vec::<TypedSignature>::with_capacity(
sigs_reader sigs_reader
.len() .len()
.try_into() .try_into()
.map_err(RPCError::map_internal("too many signatures"))?, .map_err(RPCError::map_internal("too many signatures"))?,
); );
for s in sigs_reader.iter() { for s in sigs_reader.iter() {
let sig = decode_signature(&s); let sig = decode_typed_signature(&s);
signatures.push(sig); signatures.push(sig);
} }
let version = reader.get_version();
let sequencing = decode_sequencing(reader.get_sequencing().map_err(RPCError::protocol)?); let sequencing = decode_sequencing(reader.get_sequencing().map_err(RPCError::protocol)?);
let n_reader = reader.get_nonce().map_err(RPCError::protocol)?; let n_reader = reader.get_nonce().map_err(RPCError::protocol)?;
let nonce = decode_nonce(&n_reader); let nonce = decode_nonce(&n_reader);
let data = reader.get_data().map_err(RPCError::protocol)?.to_vec(); let data = reader.get_data().map_err(RPCError::protocol)?.to_vec();
Ok(RoutedOperation { Ok(RoutedOperation {
version,
sequencing, sequencing,
signatures, signatures,
nonce, nonce,
@ -54,7 +50,6 @@ impl RoutedOperation {
&self, &self,
builder: &mut veilid_capnp::routed_operation::Builder, builder: &mut veilid_capnp::routed_operation::Builder,
) -> Result<(), RPCError> { ) -> Result<(), RPCError> {
builder.reborrow().set_version(self.version);
builder builder
.reborrow() .reborrow()
.set_sequencing(encode_sequencing(self.sequencing)); .set_sequencing(encode_sequencing(self.sequencing));
@ -66,7 +61,7 @@ impl RoutedOperation {
); );
for (i, sig) in self.signatures.iter().enumerate() { for (i, sig) in self.signatures.iter().enumerate() {
let mut sig_builder = sigs_builder.reborrow().get(i as u32); let mut sig_builder = sigs_builder.reborrow().get(i as u32);
encode_signature(sig, &mut sig_builder); encode_typed_signature(sig, &mut sig_builder);
} }
let mut n_builder = builder.reborrow().init_nonce(); let mut n_builder = builder.reborrow().init_nonce();
encode_nonce(&self.nonce, &mut n_builder); encode_nonce(&self.nonce, &mut n_builder);

View File

@ -2,7 +2,7 @@ use super::*;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RPCOperationSupplyBlockQ { pub struct RPCOperationSupplyBlockQ {
pub block_id: DHTKey, pub block_id: PublicKey,
} }
impl RPCOperationSupplyBlockQ { impl RPCOperationSupplyBlockQ {

View File

@ -23,7 +23,7 @@ pub fn encode_signed_direct_node_info(
pub fn decode_signed_direct_node_info( pub fn decode_signed_direct_node_info(
reader: &veilid_capnp::signed_direct_node_info::Reader, reader: &veilid_capnp::signed_direct_node_info::Reader,
node_id: &DHTKey, node_id: &PublicKey,
) -> Result<SignedDirectNodeInfo, RPCError> { ) -> Result<SignedDirectNodeInfo, RPCError> {
let ni_reader = reader let ni_reader = reader
.reborrow() .reborrow()

View File

@ -20,7 +20,7 @@ pub fn encode_signed_node_info(
pub fn decode_signed_node_info( pub fn decode_signed_node_info(
reader: &veilid_capnp::signed_node_info::Reader, reader: &veilid_capnp::signed_node_info::Reader,
node_id: &DHTKey, node_id: &PublicKey,
) -> Result<SignedNodeInfo, RPCError> { ) -> Result<SignedNodeInfo, RPCError> {
match reader match reader
.which() .which()

View File

@ -26,7 +26,7 @@ pub fn encode_signed_relayed_node_info(
pub fn decode_signed_relayed_node_info( pub fn decode_signed_relayed_node_info(
reader: &veilid_capnp::signed_relayed_node_info::Reader, reader: &veilid_capnp::signed_relayed_node_info::Reader,
node_id: &DHTKey, node_id: &PublicKey,
) -> Result<SignedRelayedNodeInfo, RPCError> { ) -> Result<SignedRelayedNodeInfo, RPCError> {
let ni_reader = reader let ni_reader = reader
.reborrow() .reborrow()

View File

@ -15,7 +15,7 @@ pub enum Destination {
/// The relay to send to /// The relay to send to
relay: NodeRef, relay: NodeRef,
/// The final destination the relay should send to /// The final destination the relay should send to
target: DHTKey, target: PublicKey,
/// Require safety route or not /// Require safety route or not
safety_selection: SafetySelection, safety_selection: SafetySelection,
}, },
@ -36,7 +36,7 @@ impl Destination {
safety_selection: SafetySelection::Unsafe(sequencing), safety_selection: SafetySelection::Unsafe(sequencing),
} }
} }
pub fn relay(relay: NodeRef, target: DHTKey) -> Self { pub fn relay(relay: NodeRef, target: PublicKey) -> Self {
let sequencing = relay.sequencing(); let sequencing = relay.sequencing();
Self::Relay { Self::Relay {
relay, relay,

View File

@ -53,7 +53,7 @@ struct RPCMessageHeaderDetailDirect {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct RPCMessageHeaderDetailSafetyRouted { struct RPCMessageHeaderDetailSafetyRouted {
/// Remote safety route used /// Remote safety route used
remote_safety_route: DHTKey, remote_safety_route: PublicKey,
/// The sequencing used for this route /// The sequencing used for this route
sequencing: Sequencing, sequencing: Sequencing,
} }
@ -62,9 +62,9 @@ struct RPCMessageHeaderDetailSafetyRouted {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct RPCMessageHeaderDetailPrivateRouted { struct RPCMessageHeaderDetailPrivateRouted {
/// Remote safety route used (or possibly node id the case of no safety route) /// Remote safety route used (or possibly node id the case of no safety route)
remote_safety_route: DHTKey, remote_safety_route: PublicKey,
/// The private route we received the rpc over /// The private route we received the rpc over
private_route: DHTKey, private_route: PublicKey,
// The safety spec for replying to this private routed rpc // The safety spec for replying to this private routed rpc
safety_spec: SafetySpec, safety_spec: SafetySpec,
} }
@ -141,9 +141,9 @@ struct WaitableReply {
node_ref: NodeRef, node_ref: NodeRef,
send_ts: Timestamp, send_ts: Timestamp,
send_data_kind: SendDataKind, send_data_kind: SendDataKind,
safety_route: Option<DHTKey>, safety_route: Option<PublicKey>,
remote_private_route: Option<DHTKey>, remote_private_route: Option<PublicKey>,
reply_private_route: Option<DHTKey>, reply_private_route: Option<PublicKey>,
} }
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
@ -164,17 +164,17 @@ struct RenderedOperation {
/// The rendered operation bytes /// The rendered operation bytes
message: Vec<u8>, message: Vec<u8>,
/// Destination node id we're sending to /// Destination node id we're sending to
node_id: DHTKey, node_id: PublicKey,
/// Node to send envelope to (may not be destination node id in case of relay) /// Node to send envelope to (may not be destination node id in case of relay)
node_ref: NodeRef, node_ref: NodeRef,
/// Total safety + private route hop count + 1 hop for the initial send /// Total safety + private route hop count + 1 hop for the initial send
hop_count: usize, hop_count: usize,
/// The safety route used to send the message /// The safety route used to send the message
safety_route: Option<DHTKey>, safety_route: Option<PublicKey>,
/// The private route used to send the message /// The private route used to send the message
remote_private_route: Option<DHTKey>, remote_private_route: Option<PublicKey>,
/// The private route requested to receive the reply /// The private route requested to receive the reply
reply_private_route: Option<DHTKey>, reply_private_route: Option<PublicKey>,
} }
/// Node information exchanged during every RPC message /// Node information exchanged during every RPC message
@ -371,7 +371,7 @@ impl RPCProcessor {
/// If no node was found in the timeout, this returns None /// If no node was found in the timeout, this returns None
pub async fn search_dht_single_key( pub async fn search_dht_single_key(
&self, &self,
_node_id: DHTKey, _node_id: PublicKey,
_count: u32, _count: u32,
_fanout: u32, _fanout: u32,
_timeout: Option<u64>, _timeout: Option<u64>,
@ -386,7 +386,7 @@ impl RPCProcessor {
/// Search the DHT for the 'count' closest nodes to a key, adding them all to the routing table if they are not there and returning their node references /// Search the DHT for the 'count' closest nodes to a key, adding them all to the routing table if they are not there and returning their node references
pub async fn search_dht_multi_key( pub async fn search_dht_multi_key(
&self, &self,
_node_id: DHTKey, _node_id: PublicKey,
_count: u32, _count: u32,
_fanout: u32, _fanout: u32,
_timeout: Option<u64>, _timeout: Option<u64>,
@ -399,7 +399,7 @@ impl RPCProcessor {
/// Note: This routine can possible be recursive, hence the SendPinBoxFuture async form /// Note: This routine can possible be recursive, hence the SendPinBoxFuture async form
pub fn resolve_node( pub fn resolve_node(
&self, &self,
node_id: DHTKey, node_id: PublicKey,
) -> SendPinBoxFuture<Result<Option<NodeRef>, RPCError>> { ) -> SendPinBoxFuture<Result<Option<NodeRef>, RPCError>> {
let this = self.clone(); let this = self.clone();
Box::pin(async move { Box::pin(async move {
@ -483,7 +483,7 @@ impl RPCProcessor {
&self, &self,
safety_selection: SafetySelection, safety_selection: SafetySelection,
remote_private_route: PrivateRoute, remote_private_route: PrivateRoute,
reply_private_route: Option<DHTKey>, reply_private_route: Option<PublicKey>,
message_data: Vec<u8>, message_data: Vec<u8>,
) -> Result<NetworkResult<RenderedOperation>, RPCError> { ) -> Result<NetworkResult<RenderedOperation>, RPCError> {
let routing_table = self.routing_table(); let routing_table = self.routing_table();
@ -764,8 +764,8 @@ impl RPCProcessor {
rpc_kind: RPCKind, rpc_kind: RPCKind,
send_ts: Timestamp, send_ts: Timestamp,
node_ref: NodeRef, node_ref: NodeRef,
safety_route: Option<DHTKey>, safety_route: Option<PublicKey>,
remote_private_route: Option<DHTKey>, remote_private_route: Option<PublicKey>,
) { ) {
let wants_answer = matches!(rpc_kind, RPCKind::Question); let wants_answer = matches!(rpc_kind, RPCKind::Question);
@ -793,9 +793,9 @@ impl RPCProcessor {
&self, &self,
send_ts: Timestamp, send_ts: Timestamp,
node_ref: NodeRef, node_ref: NodeRef,
safety_route: Option<DHTKey>, safety_route: Option<PublicKey>,
remote_private_route: Option<DHTKey>, remote_private_route: Option<PublicKey>,
private_route: Option<DHTKey>, private_route: Option<PublicKey>,
) { ) {
// Record for node if this was not sent via a route // Record for node if this was not sent via a route
if safety_route.is_none() && remote_private_route.is_none() { if safety_route.is_none() && remote_private_route.is_none() {
@ -833,8 +833,8 @@ impl RPCProcessor {
send_ts: Timestamp, send_ts: Timestamp,
bytes: ByteCount, bytes: ByteCount,
node_ref: NodeRef, node_ref: NodeRef,
safety_route: Option<DHTKey>, safety_route: Option<PublicKey>,
remote_private_route: Option<DHTKey>, remote_private_route: Option<PublicKey>,
) { ) {
let wants_answer = matches!(rpc_kind, RPCKind::Question); let wants_answer = matches!(rpc_kind, RPCKind::Question);
@ -870,9 +870,9 @@ impl RPCProcessor {
recv_ts: Timestamp, recv_ts: Timestamp,
bytes: ByteCount, bytes: ByteCount,
node_ref: NodeRef, node_ref: NodeRef,
safety_route: Option<DHTKey>, safety_route: Option<PublicKey>,
remote_private_route: Option<DHTKey>, remote_private_route: Option<PublicKey>,
reply_private_route: Option<DHTKey>, reply_private_route: Option<PublicKey>,
) { ) {
// Record stats for remote node if this was direct // Record stats for remote node if this was direct
if safety_route.is_none() && remote_private_route.is_none() && reply_private_route.is_none() if safety_route.is_none() && remote_private_route.is_none() && reply_private_route.is_none()
@ -1388,7 +1388,7 @@ impl RPCProcessor {
#[instrument(level = "trace", skip(self, body), err)] #[instrument(level = "trace", skip(self, body), err)]
pub fn enqueue_safety_routed_message( pub fn enqueue_safety_routed_message(
&self, &self,
remote_safety_route: DHTKey, remote_safety_route: PublicKey,
sequencing: Sequencing, sequencing: Sequencing,
body: Vec<u8>, body: Vec<u8>,
) -> EyreResult<()> { ) -> EyreResult<()> {
@ -1417,8 +1417,8 @@ impl RPCProcessor {
#[instrument(level = "trace", skip(self, body), err)] #[instrument(level = "trace", skip(self, body), err)]
pub fn enqueue_private_routed_message( pub fn enqueue_private_routed_message(
&self, &self,
remote_safety_route: DHTKey, remote_safety_route: PublicKey,
private_route: DHTKey, private_route: PublicKey,
safety_spec: SafetySpec, safety_spec: SafetySpec,
body: Vec<u8>, body: Vec<u8>,
) -> EyreResult<()> { ) -> EyreResult<()> {

View File

@ -11,7 +11,7 @@ impl RPCProcessor {
pub async fn rpc_call_find_node( pub async fn rpc_call_find_node(
self, self,
dest: Destination, dest: Destination,
key: DHTKey, key: PublicKey,
) -> Result<NetworkResult<Answer<Vec<PeerInfo>>>, RPCError> { ) -> Result<NetworkResult<Answer<Vec<PeerInfo>>>, RPCError> {
// Ensure destination never has a private route // Ensure destination never has a private route
if matches!( if matches!(
@ -100,7 +100,7 @@ impl RPCProcessor {
// find N nodes closest to the target node in our routing table // find N nodes closest to the target node in our routing table
let filter = Box::new( let filter = Box::new(
move |rti: &RoutingTableInner, _k: DHTKey, v: Option<Arc<BucketEntry>>| { move |rti: &RoutingTableInner, _k: PublicKey, v: Option<Arc<BucketEntry>>| {
rti.filter_has_valid_signed_node_info(RoutingDomain::PublicInternet, true, v) rti.filter_has_valid_signed_node_info(RoutingDomain::PublicInternet, true, v)
}, },
) as RoutingTableEntryFilter; ) as RoutingTableEntryFilter;

View File

@ -77,7 +77,7 @@ impl RPCProcessor {
&self, &self,
routed_operation: RoutedOperation, routed_operation: RoutedOperation,
next_route_node: RouteNode, next_route_node: RouteNode,
safety_route_public_key: DHTKey, safety_route_public_key: PublicKey,
next_private_route: PrivateRoute, next_private_route: PrivateRoute,
) -> Result<NetworkResult<()>, RPCError> { ) -> Result<NetworkResult<()>, RPCError> {
// Make sure hop count makes sense // Make sure hop count makes sense
@ -142,7 +142,7 @@ impl RPCProcessor {
&self, &self,
_detail: RPCMessageHeaderDetailDirect, _detail: RPCMessageHeaderDetailDirect,
routed_operation: RoutedOperation, routed_operation: RoutedOperation,
remote_sr_pubkey: DHTKey, remote_sr_pubkey: PublicKey,
) -> Result<NetworkResult<()>, RPCError> { ) -> Result<NetworkResult<()>, RPCError> {
// Now that things are valid, decrypt the routed operation with DEC(nonce, DH(the SR's public key, the PR's (or node's) secret) // Now that things are valid, decrypt the routed operation with DEC(nonce, DH(the SR's public key, the PR's (or node's) secret)
@ -177,8 +177,8 @@ impl RPCProcessor {
&self, &self,
detail: RPCMessageHeaderDetailDirect, detail: RPCMessageHeaderDetailDirect,
routed_operation: RoutedOperation, routed_operation: RoutedOperation,
remote_sr_pubkey: DHTKey, remote_sr_pubkey: PublicKey,
pr_pubkey: DHTKey, pr_pubkey: PublicKey,
) -> Result<NetworkResult<()>, RPCError> { ) -> Result<NetworkResult<()>, RPCError> {
// Get sender id // Get sender id
let sender_id = detail.envelope.get_sender_id(); let sender_id = detail.envelope.get_sender_id();
@ -237,8 +237,8 @@ impl RPCProcessor {
&self, &self,
detail: RPCMessageHeaderDetailDirect, detail: RPCMessageHeaderDetailDirect,
routed_operation: RoutedOperation, routed_operation: RoutedOperation,
remote_sr_pubkey: DHTKey, remote_sr_pubkey: PublicKey,
pr_pubkey: DHTKey, pr_pubkey: PublicKey,
) -> Result<NetworkResult<()>, RPCError> { ) -> Result<NetworkResult<()>, RPCError> {
// If the private route public key is our node id, then this was sent via safety route to our node directly // If the private route public key is our node id, then this was sent via safety route to our node directly
@ -260,7 +260,7 @@ impl RPCProcessor {
pub(crate) async fn process_private_route_first_hop( pub(crate) async fn process_private_route_first_hop(
&self, &self,
mut routed_operation: RoutedOperation, mut routed_operation: RoutedOperation,
sr_pubkey: DHTKey, sr_pubkey: PublicKey,
mut private_route: PrivateRoute, mut private_route: PrivateRoute,
) -> Result<NetworkResult<()>, RPCError> { ) -> Result<NetworkResult<()>, RPCError> {
let Some(pr_first_hop) = private_route.pop_first_hop() else { let Some(pr_first_hop) = private_route.pop_first_hop() else {
@ -312,7 +312,7 @@ impl RPCProcessor {
} }
/// Decrypt route hop data and sign routed operation /// Decrypt route hop data and sign routed operation
pub(crate) fn decrypt_private_route_hop_data(&self, route_hop_data: &RouteHopData, pr_pubkey: &DHTKey, route_operation: &mut RoutedOperation) -> Result<NetworkResult<RouteHop>, RPCError> pub(crate) fn decrypt_private_route_hop_data(&self, route_hop_data: &RouteHopData, pr_pubkey: &PublicKey, route_operation: &mut RoutedOperation) -> Result<NetworkResult<RouteHop>, RPCError>
{ {
// Decrypt the blob with DEC(nonce, DH(the PR's public key, this hop's secret) // Decrypt the blob with DEC(nonce, DH(the PR's public key, this hop's secret)
let node_id_secret = self.routing_table.node_id_secret(); let node_id_secret = self.routing_table.node_id_secret();

View File

@ -102,7 +102,7 @@ impl RPCProcessor {
dial_info.clone(), dial_info.clone(),
); );
let will_validate_dial_info_filter = Box::new( let will_validate_dial_info_filter = Box::new(
move |rti: &RoutingTableInner, _k: DHTKey, v: Option<Arc<BucketEntry>>| { move |rti: &RoutingTableInner, _k: PublicKey, v: Option<Arc<BucketEntry>>| {
let entry = v.unwrap(); let entry = v.unwrap();
entry.with(rti, move |_rti, e| { entry.with(rti, move |_rti, e| {
if let Some(status) = &e.node_status(routing_domain) { if let Some(status) = &e.node_status(routing_domain) {

View File

@ -132,9 +132,9 @@ pub async fn test_frozen(ts: TableStore) {
assert!(db.store_rkyv(0, b"asdf", &dht_key).await.is_ok()); assert!(db.store_rkyv(0, b"asdf", &dht_key).await.is_ok());
assert_eq!(db.load_rkyv::<DHTKey>(0, b"qwer").unwrap(), None); assert_eq!(db.load_rkyv::<PublicKey>(0, b"qwer").unwrap(), None);
let d = match db.load_rkyv::<DHTKey>(0, b"asdf") { let d = match db.load_rkyv::<PublicKey>(0, b"asdf") {
Ok(x) => x, Ok(x) => x,
Err(e) => { Err(e) => {
panic!("couldn't decode: {}", e); panic!("couldn't decode: {}", e);
@ -148,7 +148,7 @@ pub async fn test_frozen(ts: TableStore) {
); );
assert!( assert!(
db.load_rkyv::<DHTKey>(1, b"foo").is_err(), db.load_rkyv::<PublicKey>(1, b"foo").is_err(),
"should fail to unfreeze" "should fail to unfreeze"
); );
} }

View File

@ -192,8 +192,8 @@ fn config_callback(key: String) -> ConfigCallbackReturn {
"network.client_whitelist_timeout_ms" => Ok(Box::new(300_000u32)), "network.client_whitelist_timeout_ms" => Ok(Box::new(300_000u32)),
"network.reverse_connection_receipt_time_ms" => Ok(Box::new(5_000u32)), "network.reverse_connection_receipt_time_ms" => Ok(Box::new(5_000u32)),
"network.hole_punch_receipt_time_ms" => Ok(Box::new(5_000u32)), "network.hole_punch_receipt_time_ms" => Ok(Box::new(5_000u32)),
"network.node_id" => Ok(Box::new(Option::<DHTKey>::None)), "network.node_id" => Ok(Box::new(Option::<PublicKey>::None)),
"network.node_id_secret" => Ok(Box::new(Option::<DHTKeySecret>::None)), "network.node_id_secret" => Ok(Box::new(Option::<SecretKey>::None)),
"network.bootstrap" => Ok(Box::new(Vec::<String>::new())), "network.bootstrap" => Ok(Box::new(Vec::<String>::new())),
"network.bootstrap_nodes" => Ok(Box::new(Vec::<String>::new())), "network.bootstrap_nodes" => Ok(Box::new(Vec::<String>::new())),
"network.routing_table.limit_over_attached" => Ok(Box::new(64u32)), "network.routing_table.limit_over_attached" => Ok(Box::new(64u32)),

View File

@ -91,7 +91,7 @@ pub async fn test_signed_node_info() {
let (pkey2, skey2) = generate_secret(); let (pkey2, skey2) = generate_secret();
let sni2 = SignedRelayedNodeInfo::with_secret( let sni2 = SignedRelayedNodeInfo::make_signatures(
NodeId::new(pkey2.clone()), NodeId::new(pkey2.clone()),
node_info2.clone(), node_info2.clone(),
NodeId::new(pkey.clone()), NodeId::new(pkey.clone()),

View File

@ -12,7 +12,7 @@ pub async fn run_all_tests() {
info!("TEST: test_host_interface"); info!("TEST: test_host_interface");
test_host_interface::test_all().await; test_host_interface::test_all().await;
info!("TEST: test_dht_key"); info!("TEST: test_dht_key");
test_dht_key::test_all().await; test_types::test_all().await;
info!("TEST: test_veilid_core"); info!("TEST: test_veilid_core");
test_veilid_core::test_all().await; test_veilid_core::test_all().await;
info!("TEST: test_veilid_config"); info!("TEST: test_veilid_config");
@ -85,7 +85,7 @@ cfg_if! {
fn run_test_dht_key() { fn run_test_dht_key() {
setup(); setup();
block_on(async { block_on(async {
test_dht_key::test_all().await; test_types::test_all().await;
}); });
} }

View File

@ -167,7 +167,7 @@ impl VeilidAPI {
// Private route allocation // Private route allocation
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
pub async fn new_private_route(&self) -> Result<(DHTKey, Vec<u8>), VeilidAPIError> { pub async fn new_private_route(&self) -> Result<(PublicKey, Vec<u8>), VeilidAPIError> {
self.new_custom_private_route(Stability::default(), Sequencing::default()) self.new_custom_private_route(Stability::default(), Sequencing::default())
.await .await
} }
@ -177,7 +177,7 @@ impl VeilidAPI {
&self, &self,
stability: Stability, stability: Stability,
sequencing: Sequencing, sequencing: Sequencing,
) -> Result<(DHTKey, Vec<u8>), VeilidAPIError> { ) -> Result<(PublicKey, Vec<u8>), VeilidAPIError> {
let default_route_hop_count: usize = { let default_route_hop_count: usize = {
let config = self.config()?; let config = self.config()?;
let c = config.get(); let c = config.get();
@ -223,14 +223,14 @@ impl VeilidAPI {
} }
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
pub fn import_remote_private_route(&self, blob: Vec<u8>) -> Result<DHTKey, VeilidAPIError> { pub fn import_remote_private_route(&self, blob: Vec<u8>) -> Result<PublicKey, VeilidAPIError> {
let rss = self.routing_table()?.route_spec_store(); let rss = self.routing_table()?.route_spec_store();
rss.import_remote_private_route(blob) rss.import_remote_private_route(blob)
.map_err(|e| VeilidAPIError::invalid_argument(e, "blob", "private route blob")) .map_err(|e| VeilidAPIError::invalid_argument(e, "blob", "private route blob"))
} }
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
pub fn release_private_route(&self, key: &DHTKey) -> Result<(), VeilidAPIError> { pub fn release_private_route(&self, key: &PublicKey) -> Result<(), VeilidAPIError> {
let rss = self.routing_table()?.route_spec_store(); let rss = self.routing_table()?.route_spec_store();
if rss.release_route(key) { if rss.release_route(key) {
Ok(()) Ok(())

View File

@ -7,7 +7,7 @@ use routing_table::*;
#[derive(Default, Debug)] #[derive(Default, Debug)]
struct DebugCache { struct DebugCache {
imported_routes: Vec<DHTKey>, imported_routes: Vec<PublicKey>,
} }
static DEBUG_CACHE: Mutex<DebugCache> = Mutex::new(DebugCache { static DEBUG_CACHE: Mutex<DebugCache> = Mutex::new(DebugCache {
@ -30,12 +30,12 @@ fn get_string(text: &str) -> Option<String> {
Some(text.to_owned()) Some(text.to_owned())
} }
fn get_route_id(rss: RouteSpecStore) -> impl Fn(&str) -> Option<DHTKey> { fn get_route_id(rss: RouteSpecStore) -> impl Fn(&str) -> Option<PublicKey> {
return move |text: &str| { return move |text: &str| {
if text.is_empty() { if text.is_empty() {
return None; return None;
} }
match DHTKey::try_decode(text).ok() { match PublicKey::try_decode(text).ok() {
Some(key) => { Some(key) => {
let routes = rss.list_allocated_routes(|k, _| Some(*k)); let routes = rss.list_allocated_routes(|k, _| Some(*k));
if routes.contains(&key) { if routes.contains(&key) {
@ -187,8 +187,8 @@ fn get_destination(routing_table: RoutingTable) -> impl FnOnce(&str) -> Option<D
fn get_number(text: &str) -> Option<usize> { fn get_number(text: &str) -> Option<usize> {
usize::from_str(text).ok() usize::from_str(text).ok()
} }
fn get_dht_key(text: &str) -> Option<DHTKey> { fn get_dht_key(text: &str) -> Option<PublicKey> {
DHTKey::try_decode(text).ok() PublicKey::try_decode(text).ok()
} }
fn get_node_ref(routing_table: RoutingTable) -> impl FnOnce(&str) -> Option<NodeRef> { fn get_node_ref(routing_table: RoutingTable) -> impl FnOnce(&str) -> Option<NodeRef> {

View File

@ -108,7 +108,7 @@ pub enum VeilidAPIError {
#[error("Shutdown")] #[error("Shutdown")]
Shutdown, Shutdown,
#[error("Key not found: {key}")] #[error("Key not found: {key}")]
KeyNotFound { key: DHTKey }, KeyNotFound { key: PublicKey },
#[error("No connection: {message}")] #[error("No connection: {message}")]
NoConnection { message: String }, NoConnection { message: String },
#[error("No peer info: {node_id}")] #[error("No peer info: {node_id}")]
@ -147,7 +147,7 @@ impl VeilidAPIError {
pub fn shutdown() -> Self { pub fn shutdown() -> Self {
Self::Shutdown Self::Shutdown
} }
pub fn key_not_found(key: DHTKey) -> Self { pub fn key_not_found(key: PublicKey) -> Self {
Self::KeyNotFound { key } Self::KeyNotFound { key }
} }
pub fn no_connection<T: ToString>(msg: T) -> Self { pub fn no_connection<T: ToString>(msg: T) -> Self {

View File

@ -19,8 +19,7 @@ pub use types::*;
pub use alloc::string::ToString; pub use alloc::string::ToString;
pub use attachment_manager::AttachmentManager; pub use attachment_manager::AttachmentManager;
pub use core::str::FromStr; pub use core::str::FromStr;
pub use crypto::Crypto; pub use crypto::*;
pub use crypto::{generate_secret, sign, verify, DHTKey, DHTKeySecret, DHTSignature, Nonce};
pub use intf::BlockStore; pub use intf::BlockStore;
pub use intf::ProtectedStore; pub use intf::ProtectedStore;
pub use intf::{TableDB, TableDBTransaction, TableStore}; pub use intf::{TableDB, TableDBTransaction, TableStore};

View File

@ -5,7 +5,7 @@ use super::*;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Target { pub enum Target {
NodeId(NodeId), NodeId(NodeId),
PrivateRoute(DHTKey), PrivateRoute(PublicKey),
} }
pub struct RoutingContextInner {} pub struct RoutingContextInner {}

View File

@ -108,7 +108,7 @@ pub struct VeilidLog {
pub struct VeilidAppMessage { pub struct VeilidAppMessage {
/// Some(sender) if the message was sent directly, None if received via a private/safety route /// Some(sender) if the message was sent directly, None if received via a private/safety route
#[serde(with = "opt_json_as_string")] #[serde(with = "opt_json_as_string")]
pub sender: Option<NodeId>, pub sender: Option<TypedKey>,
/// The content of the message to deliver to the application /// The content of the message to deliver to the application
#[serde(with = "json_as_base64")] #[serde(with = "json_as_base64")]
pub message: Vec<u8>, pub message: Vec<u8>,
@ -121,7 +121,7 @@ pub struct VeilidAppMessage {
pub struct VeilidAppCall { pub struct VeilidAppCall {
/// Some(sender) if the request was sent directly, None if received via a private/safety route /// Some(sender) if the request was sent directly, None if received via a private/safety route
#[serde(with = "opt_json_as_string")] #[serde(with = "opt_json_as_string")]
pub sender: Option<NodeId>, pub sender: Option<TypedKey>,
/// The content of the request to deliver to the application /// The content of the request to deliver to the application
#[serde(with = "json_as_base64")] #[serde(with = "json_as_base64")]
pub message: Vec<u8>, pub message: Vec<u8>,
@ -203,7 +203,7 @@ pub struct VeilidStateAttachment {
)] )]
#[archive_attr(repr(C), derive(CheckBytes))] #[archive_attr(repr(C), derive(CheckBytes))]
pub struct PeerTableData { pub struct PeerTableData {
pub node_id: DHTKey, pub node_id: TypedKey,
pub peer_address: PeerAddress, pub peer_address: PeerAddress,
pub peer_stats: PeerStats, pub peer_stats: PeerStats,
} }
@ -226,8 +226,8 @@ pub struct VeilidStateNetwork {
)] )]
#[archive_attr(repr(C), derive(CheckBytes))] #[archive_attr(repr(C), derive(CheckBytes))]
pub struct VeilidStateRoute { pub struct VeilidStateRoute {
pub dead_routes: Vec<DHTKey>, pub dead_routes: Vec<PublicKey>,
pub dead_remote_routes: Vec<DHTKey>, pub dead_remote_routes: Vec<PublicKey>,
} }
#[derive( #[derive(
@ -262,42 +262,6 @@ pub struct VeilidState {
///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////
/// ///
#[derive(
Clone,
Debug,
Default,
PartialOrd,
PartialEq,
Eq,
Ord,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes))]
pub struct NodeId {
pub key: DHTKey,
}
impl NodeId {
pub fn new(key: DHTKey) -> Self {
Self { key }
}
}
impl fmt::Display for NodeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{}", self.key.encode())
}
}
impl FromStr for NodeId {
type Err = VeilidAPIError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self {
key: DHTKey::try_decode(s)?,
})
}
}
#[derive( #[derive(
Clone, Clone,
@ -315,22 +279,12 @@ impl FromStr for NodeId {
)] )]
#[archive_attr(repr(C), derive(CheckBytes))] #[archive_attr(repr(C), derive(CheckBytes))]
pub struct ValueKey { pub struct ValueKey {
pub key: DHTKey, pub key: TypedKey,
pub subkey: Option<String>, pub subkey: u32,
} }
impl ValueKey { impl ValueKey {
pub fn new(key: DHTKey) -> Self { pub fn new(key: TypedKey, subkey: u32) -> Self {
Self { key, subkey: None } Self { key, subkey }
}
pub fn new_subkey(key: DHTKey, subkey: String) -> Self {
Self {
key,
subkey: if subkey.is_empty() {
None
} else {
Some(subkey)
},
}
} }
} }
@ -366,30 +320,6 @@ impl ValueData {
} }
} }
#[derive(
Clone,
Debug,
Default,
PartialOrd,
PartialEq,
Eq,
Ord,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes))]
pub struct BlockId {
pub key: DHTKey,
}
impl BlockId {
pub fn new(key: DHTKey) -> Self {
Self { key }
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////
// Keep member order appropriate for sorting < preference // Keep member order appropriate for sorting < preference
@ -550,7 +480,7 @@ impl SafetySelection {
#[archive_attr(repr(C), derive(CheckBytes))] #[archive_attr(repr(C), derive(CheckBytes))]
pub struct SafetySpec { pub struct SafetySpec {
/// preferred safety route if it still exists /// preferred safety route if it still exists
pub preferred_route: Option<DHTKey>, pub preferred_route: Option<PublicKey>,
/// must be greater than 0 /// must be greater than 0
pub hop_count: usize, pub hop_count: usize,
/// prefer reliability over speed /// prefer reliability over speed
@ -713,8 +643,8 @@ pub struct NodeInfo {
pub outbound_protocols: ProtocolTypeSet, pub outbound_protocols: ProtocolTypeSet,
#[with(RkyvEnumSet)] #[with(RkyvEnumSet)]
pub address_types: AddressTypeSet, pub address_types: AddressTypeSet,
pub min_version: u8, pub envelope_support: Vec<u8>,
pub max_version: u8, pub crypto_support: Vec<CryptoKind>,
pub dial_info_detail_list: Vec<DialInfoDetail>, pub dial_info_detail_list: Vec<DialInfoDetail>,
} }
@ -1885,37 +1815,44 @@ impl MatchesDialInfoFilter for DialInfo {
pub struct SignedDirectNodeInfo { pub struct SignedDirectNodeInfo {
pub node_info: NodeInfo, pub node_info: NodeInfo,
pub timestamp: Timestamp, pub timestamp: Timestamp,
pub signature: Option<DHTSignature>, pub signatures: Vec<TypedSignature>,
} }
impl SignedDirectNodeInfo { impl SignedDirectNodeInfo {
pub fn new( pub fn new(
node_id: NodeId, crypto: Crypto,
node_info: NodeInfo, node_info: NodeInfo,
timestamp: Timestamp, timestamp: Timestamp,
signature: DHTSignature, keyed_signatures: Vec<TypedKeySignature>,
) -> Result<Self, VeilidAPIError> { ) -> Result<Self, VeilidAPIError> {
let node_info_bytes = Self::make_signature_bytes(&node_info, timestamp)?; let node_info_bytes = Self::make_signature_bytes(&node_info, timestamp)?;
verify(&node_id.key, &node_info_bytes, &signature)?; let signatures = crypto.verify_signatures(
&node_info_bytes,
&keyed_signatures,
TypedSignature::from_keyed,
)?;
Ok(Self { Ok(Self {
node_info, node_info,
timestamp, timestamp,
signature: Some(signature), signatures,
}) })
} }
pub fn with_secret( pub fn make_signatures(
node_id: NodeId, crypto: Crypto,
node_info: NodeInfo, node_info: NodeInfo,
secret: &DHTKeySecret, keypairs: Vec<TypedKeyPair>,
) -> Result<Self, VeilidAPIError> { ) -> Result<Self, VeilidAPIError> {
let timestamp = get_aligned_timestamp(); let timestamp = get_aligned_timestamp();
let node_info_bytes = Self::make_signature_bytes(&node_info, timestamp)?; let node_info_bytes = Self::make_signature_bytes(&node_info, timestamp)?;
let signature = sign(&node_id.key, secret, &node_info_bytes)?; let signatures = crypto.generate_signatures(
&node_info_bytes,
&keypairs,
TypedSignature::from_pair_sig,
)?;
Ok(Self { Ok(Self {
node_info, node_info,
timestamp, timestamp,
signature: Some(signature), signatures,
}) })
} }
@ -1940,13 +1877,13 @@ impl SignedDirectNodeInfo {
pub fn with_no_signature(node_info: NodeInfo) -> Self { pub fn with_no_signature(node_info: NodeInfo) -> Self {
Self { Self {
node_info, node_info,
signature: None, signatures: Vec::new(),
timestamp: get_aligned_timestamp(), timestamp: get_aligned_timestamp(),
} }
} }
pub fn has_valid_signature(&self) -> bool { pub fn has_any_signature(&self) -> bool {
self.signature.is_some() !self.signatures.is_empty()
} }
} }
@ -1955,56 +1892,64 @@ impl SignedDirectNodeInfo {
#[archive_attr(repr(C), derive(CheckBytes))] #[archive_attr(repr(C), derive(CheckBytes))]
pub struct SignedRelayedNodeInfo { pub struct SignedRelayedNodeInfo {
pub node_info: NodeInfo, pub node_info: NodeInfo,
pub relay_id: NodeId, pub relay_ids: Vec<TypedKey>,
pub relay_info: SignedDirectNodeInfo, pub relay_info: SignedDirectNodeInfo,
pub timestamp: Timestamp, pub timestamp: Timestamp,
pub signature: DHTSignature, pub signatures: Vec<TypedSignature>,
} }
impl SignedRelayedNodeInfo { impl SignedRelayedNodeInfo {
pub fn new( pub fn new(
node_id: NodeId, crypto: Crypto,
node_info: NodeInfo, node_info: NodeInfo,
relay_id: NodeId, relay_ids: Vec<TypedKey>,
relay_info: SignedDirectNodeInfo, relay_info: SignedDirectNodeInfo,
timestamp: Timestamp, timestamp: Timestamp,
signature: DHTSignature, keyed_signatures: Vec<TypedKeySignature>,
) -> Result<Self, VeilidAPIError> { ) -> Result<Self, VeilidAPIError> {
let node_info_bytes = let node_info_bytes =
Self::make_signature_bytes(&node_info, &relay_id, &relay_info, timestamp)?; Self::make_signature_bytes(&node_info, &relay_ids, &relay_info, timestamp)?;
verify(&node_id.key, &node_info_bytes, &signature)?; let signatures = crypto.verify_signatures(
&node_info_bytes,
&keyed_signatures,
TypedSignature::from_keyed,
)?;
Ok(Self { Ok(Self {
node_info, node_info,
relay_id, relay_ids,
relay_info, relay_info,
signature,
timestamp, timestamp,
signatures,
}) })
} }
pub fn with_secret( pub fn make_signatures(
node_id: NodeId, crypto: Crypto,
node_info: NodeInfo, node_info: NodeInfo,
relay_id: NodeId, relay_ids: Vec<TypedKey>,
relay_info: SignedDirectNodeInfo, relay_info: SignedDirectNodeInfo,
secret: &DHTKeySecret, keypairs: Vec<TypedKeyPair>,
) -> Result<Self, VeilidAPIError> { ) -> Result<Self, VeilidAPIError> {
let timestamp = get_aligned_timestamp(); let timestamp = get_aligned_timestamp();
let node_info_bytes = let node_info_bytes =
Self::make_signature_bytes(&node_info, &relay_id, &relay_info, timestamp)?; Self::make_signature_bytes(&node_info, &relay_ids, &relay_info, timestamp)?;
let signature = sign(&node_id.key, secret, &node_info_bytes)?; let signatures = crypto.generate_signatures(
&node_info_bytes,
&keypairs,
TypedSignature::from_pair_sig,
)?;
Ok(Self { Ok(Self {
node_info, node_info,
relay_id, relay_ids,
relay_info, relay_info,
signature, signatures,
timestamp, timestamp,
}) })
} }
fn make_signature_bytes( fn make_signature_bytes(
node_info: &NodeInfo, node_info: &NodeInfo,
relay_id: &NodeId, relay_ids: &[TypedKey],
relay_info: &SignedDirectNodeInfo, relay_info: &SignedDirectNodeInfo,
timestamp: Timestamp, timestamp: Timestamp,
) -> Result<Vec<u8>, VeilidAPIError> { ) -> Result<Vec<u8>, VeilidAPIError> {
@ -2016,7 +1961,7 @@ impl SignedRelayedNodeInfo {
encode_node_info(node_info, &mut ni_builder).map_err(VeilidAPIError::internal)?; encode_node_info(node_info, &mut ni_builder).map_err(VeilidAPIError::internal)?;
sig_bytes.append(&mut builder_to_vec(ni_msg).map_err(VeilidAPIError::internal)?); sig_bytes.append(&mut builder_to_vec(ni_msg).map_err(VeilidAPIError::internal)?);
// Add relay id to signature // Add relay ids to signature
let mut rid_msg = ::capnp::message::Builder::new_default(); let mut rid_msg = ::capnp::message::Builder::new_default();
let mut rid_builder = rid_msg.init_root::<veilid_capnp::key256::Builder>(); let mut rid_builder = rid_msg.init_root::<veilid_capnp::key256::Builder>();
encode_dht_key(&relay_id.key, &mut rid_builder).map_err(VeilidAPIError::internal)?; encode_dht_key(&relay_id.key, &mut rid_builder).map_err(VeilidAPIError::internal)?;
@ -2046,7 +1991,7 @@ pub enum SignedNodeInfo {
impl SignedNodeInfo { impl SignedNodeInfo {
pub fn has_valid_signature(&self) -> bool { pub fn has_valid_signature(&self) -> bool {
match self { match self {
SignedNodeInfo::Direct(d) => d.has_valid_signature(), SignedNodeInfo::Direct(d) => d.has_any_signature(),
SignedNodeInfo::Relayed(_) => true, SignedNodeInfo::Relayed(_) => true,
} }
} }
@ -2063,10 +2008,10 @@ impl SignedNodeInfo {
SignedNodeInfo::Relayed(r) => &r.node_info, SignedNodeInfo::Relayed(r) => &r.node_info,
} }
} }
pub fn relay_id(&self) -> Option<NodeId> { pub fn relay_ids(&self) -> Vec<TypedKey> {
match self { match self {
SignedNodeInfo::Direct(_) => None, SignedNodeInfo::Direct(_) => Vec::new(),
SignedNodeInfo::Relayed(r) => Some(r.relay_id.clone()), SignedNodeInfo::Relayed(r) => r.relay_ids.clone(),
} }
} }
pub fn relay_info(&self) -> Option<&NodeInfo> { pub fn relay_info(&self) -> Option<&NodeInfo> {
@ -2079,7 +2024,7 @@ impl SignedNodeInfo {
match self { match self {
SignedNodeInfo::Direct(_) => None, SignedNodeInfo::Direct(_) => None,
SignedNodeInfo::Relayed(r) => Some(PeerInfo::new( SignedNodeInfo::Relayed(r) => Some(PeerInfo::new(
r.relay_id.clone(), r.relay_ids.clone(),
SignedNodeInfo::Direct(r.relay_info.clone()), SignedNodeInfo::Direct(r.relay_info.clone()),
)), )),
} }
@ -2127,14 +2072,14 @@ impl SignedNodeInfo {
#[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)] #[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
#[archive_attr(repr(C), derive(CheckBytes))] #[archive_attr(repr(C), derive(CheckBytes))]
pub struct PeerInfo { pub struct PeerInfo {
pub node_id: NodeId, pub node_ids: Vec<TypedKey>,
pub signed_node_info: SignedNodeInfo, pub signed_node_info: SignedNodeInfo,
} }
impl PeerInfo { impl PeerInfo {
pub fn new(node_id: NodeId, signed_node_info: SignedNodeInfo) -> Self { pub fn new(node_ids: Vec<TypedKey>, signed_node_info: SignedNodeInfo) -> Self {
Self { Self {
node_id, node_ids,
signed_node_info, signed_node_info,
} }
} }

View File

@ -316,6 +316,25 @@ pub struct VeilidConfigRPC {
pub default_route_hop_count: u8, pub default_route_hop_count: u8,
} }
/// Configure the per-crypto version configuration
///
#[derive(
Default,
Debug,
Clone,
PartialEq,
Eq,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
pub struct VeilidConfigNodeId {
pub node_id: Option<PublicKey>,
pub node_id_secret: Option<SecretKey>,
}
/// Configure the network routing table /// Configure the network routing table
/// ///
#[derive( #[derive(
@ -331,6 +350,9 @@ pub struct VeilidConfigRPC {
RkyvDeserialize, RkyvDeserialize,
)] )]
pub struct VeilidConfigRoutingTable { pub struct VeilidConfigRoutingTable {
pub node_ids: BTreeMap<CryptoKind, VeilidConfigNodeId>,
pub bootstrap: Vec<String>,
pub bootstrap_nodes: Vec<String>,
pub limit_over_attached: u32, pub limit_over_attached: u32,
pub limit_fully_attached: u32, pub limit_fully_attached: u32,
pub limit_attached_strong: u32, pub limit_attached_strong: u32,
@ -362,10 +384,6 @@ pub struct VeilidConfigNetwork {
pub client_whitelist_timeout_ms: u32, pub client_whitelist_timeout_ms: u32,
pub reverse_connection_receipt_time_ms: u32, pub reverse_connection_receipt_time_ms: u32,
pub hole_punch_receipt_time_ms: u32, pub hole_punch_receipt_time_ms: u32,
pub node_id: Option<DHTKey>,
pub node_id_secret: Option<DHTKeySecret>,
pub bootstrap: Vec<String>,
pub bootstrap_nodes: Vec<String>,
pub routing_table: VeilidConfigRoutingTable, pub routing_table: VeilidConfigRoutingTable,
pub rpc: VeilidConfigRPC, pub rpc: VeilidConfigRPC,
pub dht: VeilidConfigDHT, pub dht: VeilidConfigDHT,
@ -608,6 +626,23 @@ impl VeilidConfig {
}; };
}; };
} }
macro_rules! get_config_indexed {
($key:expr, $index:expr, $subkey:tt) => {
let keyname = format!(
"{}[{}].{}",
&stringify!($key)[6..],
$index,
&stringify!($subkey)
);
let v = cb(keyname.to_owned())?;
$key.entry($index).or_default().$subkey = match v.downcast() {
Ok(v) => *v,
Err(_) => {
apibail_generic!(format!("incorrect type for key {}", keyname))
}
};
};
}
self.update_cb = Some(update_cb); self.update_cb = Some(update_cb);
self.with_mut(|inner| { self.with_mut(|inner| {
@ -628,8 +663,6 @@ impl VeilidConfig {
get_config!(inner.protected_store.always_use_insecure_storage); get_config!(inner.protected_store.always_use_insecure_storage);
get_config!(inner.protected_store.insecure_fallback_directory); get_config!(inner.protected_store.insecure_fallback_directory);
get_config!(inner.protected_store.delete); get_config!(inner.protected_store.delete);
get_config!(inner.network.node_id);
get_config!(inner.network.node_id_secret);
get_config!(inner.network.connection_initial_timeout_ms); get_config!(inner.network.connection_initial_timeout_ms);
get_config!(inner.network.connection_inactivity_timeout_ms); get_config!(inner.network.connection_inactivity_timeout_ms);
get_config!(inner.network.max_connections_per_ip4); get_config!(inner.network.max_connections_per_ip4);
@ -639,8 +672,12 @@ impl VeilidConfig {
get_config!(inner.network.client_whitelist_timeout_ms); get_config!(inner.network.client_whitelist_timeout_ms);
get_config!(inner.network.reverse_connection_receipt_time_ms); get_config!(inner.network.reverse_connection_receipt_time_ms);
get_config!(inner.network.hole_punch_receipt_time_ms); get_config!(inner.network.hole_punch_receipt_time_ms);
get_config!(inner.network.bootstrap); for ck in &VALID_CRYPTO_KINDS {
get_config!(inner.network.bootstrap_nodes); get_config_indexed!(inner.network.routing_table.node_ids, ck, node_id);
get_config_indexed!(inner.network.routing_table.node_ids, ck, node_id_secret);
}
get_config!(inner.network.routing_table.bootstrap);
get_config!(inner.network.routing_table.bootstrap_nodes);
get_config!(inner.network.routing_table.limit_over_attached); get_config!(inner.network.routing_table.limit_over_attached);
get_config!(inner.network.routing_table.limit_fully_attached); get_config!(inner.network.routing_table.limit_fully_attached);
get_config!(inner.network.routing_table.limit_attached_strong); get_config!(inner.network.routing_table.limit_attached_strong);
@ -908,75 +945,102 @@ impl VeilidConfig {
// Get the node id from config if one is specified // Get the node id from config if one is specified
// Must be done -after- protected store startup // Must be done -after- protected store startup
pub async fn init_node_id( pub async fn init_node_ids(
&self, &self,
crypto: Crypto,
protected_store: intf::ProtectedStore, protected_store: intf::ProtectedStore,
) -> Result<(), VeilidAPIError> { ) -> Result<(), VeilidAPIError> {
let mut node_id = self.inner.read().network.node_id; for ck in VALID_CRYPTO_KINDS {
let mut node_id_secret = self.inner.read().network.node_id_secret; let vcrypto = crypto.get(ck)?;
// See if node id was previously stored in the protected store
if node_id.is_none() {
debug!("pulling node id from storage");
if let Some(s) = protected_store
.load_user_secret_string("node_id")
.await
.map_err(VeilidAPIError::internal)?
{
debug!("node id found in storage");
node_id = Some(DHTKey::try_decode(s.as_str()).map_err(VeilidAPIError::internal)?);
} else {
debug!("node id not found in storage");
}
}
// See if node id secret was previously stored in the protected store let mut node_id = self
if node_id_secret.is_none() { .inner
debug!("pulling node id secret from storage"); .read()
if let Some(s) = protected_store .network
.load_user_secret_string("node_id_secret") .routing_table
.await .node_ids
.map_err(VeilidAPIError::internal)? .get(&ck)
{ .map(|n| n.node_id)
debug!("node id secret found in storage"); .flatten();
node_id_secret = let mut node_id_secret = self
Some(DHTKeySecret::try_decode(s.as_str()).map_err(VeilidAPIError::internal)?); .inner
} else { .read()
debug!("node id secret not found in storage"); .network
} .routing_table
} .node_ids
.get(&ck)
// If we have a node id from storage, check it .map(|n| n.node_id_secret)
let (node_id, node_id_secret) = .flatten();
if let (Some(node_id), Some(node_id_secret)) = (node_id, node_id_secret) { // See if node id was previously stored in the protected store
// Validate node id if node_id.is_none() {
if !crypto::validate_key(&node_id, &node_id_secret) { debug!("pulling node_id_{} from storage", ck);
apibail_generic!("node id secret and node id key don't match"); if let Some(s) = protected_store
.load_user_secret_string(format!("node_id_v{}", version))
.await
.map_err(VeilidAPIError::internal)?
{
debug!("node id v{} found in storage", version);
node_id =
Some(PublicKey::try_decode(s.as_str()).map_err(VeilidAPIError::internal)?);
} else {
debug!("node id v{} not found in storage", version);
} }
(node_id, node_id_secret) }
} else {
// If we still don't have a valid node id, generate one
debug!("generating new node id");
generate_secret()
};
info!("Node Id is {}", node_id.encode());
// info!("Node Id Secret is {}", node_id_secret.encode());
// Save the node id / secret in storage // See if node id secret was previously stored in the protected store
protected_store if node_id_secret.is_none() {
.save_user_secret_string("node_id", node_id.encode().as_str()) debug!("pulling node id secret from storage");
.await if let Some(s) = protected_store
.map_err(VeilidAPIError::internal)?; .load_user_secret_string(format!("node_id_secret_v{}", version))
protected_store .await
.save_user_secret_string("node_id_secret", node_id_secret.encode().as_str()) .map_err(VeilidAPIError::internal)?
.await {
.map_err(VeilidAPIError::internal)?; debug!("node id v{} secret found in storage", version);
node_id_secret =
Some(SecretKey::try_decode(s.as_str()).map_err(VeilidAPIError::internal)?);
} else {
debug!("node id v{} secret not found in storage", version);
}
}
self.with_mut(|c| { // If we have a node id from storage, check it
c.network.node_id = Some(node_id); let (node_id, node_id_secret) =
c.network.node_id_secret = Some(node_id_secret); if let (Some(node_id), Some(node_id_secret)) = (node_id, node_id_secret) {
Ok(()) // Validate node id
})?; if !vcrypto.validate_keypair(&node_id, &node_id_secret) {
apibail_generic!(format!(
"version {} node id secret and node id key don't match",
version
));
}
(node_id, node_id_secret)
} else {
// If we still don't have a valid node id, generate one
debug!("generating new node id v{}", version);
vcrypto.generate_keypair()
};
info!("Node Id v{} is {}", version, node_id.encode());
// Save the node id / secret in storage
protected_store
.save_user_secret_string(format!("node_id_v{}", version), node_id.encode().as_str())
.await
.map_err(VeilidAPIError::internal)?;
protected_store
.save_user_secret_string(
format!("node_id_secret_v{}", version),
node_id_secret.encode().as_str(),
)
.await
.map_err(VeilidAPIError::internal)?;
self.with_mut(|c| {
let n = c.network.routing_table.node_ids.entry(version).or_default();
n.node_id = Some(node_id);
n.node_id_secret = Some(node_id_secret);
Ok(())
})?;
}
trace!("init_node_id complete"); trace!("init_node_id complete");
Ok(()) Ok(())

View File

@ -93,7 +93,7 @@ pub struct VeilidFFIConfig {
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
pub struct VeilidFFIKeyBlob { pub struct VeilidFFIKeyBlob {
pub key: veilid_core::DHTKey, pub key: veilid_core::PublicKey,
#[serde(with = "veilid_core::json_as_base64")] #[serde(with = "veilid_core::json_as_base64")]
pub blob: Vec<u8>, pub blob: Vec<u8>,
} }
@ -417,7 +417,7 @@ pub extern "C" fn routing_context_with_sequencing(id: u32, sequencing: FfiStr) -
#[no_mangle] #[no_mangle]
pub extern "C" fn routing_context_app_call(port: i64, id: u32, target: FfiStr, request: FfiStr) { pub extern "C" fn routing_context_app_call(port: i64, id: u32, target: FfiStr, request: FfiStr) {
let target: veilid_core::DHTKey = let target: veilid_core::PublicKey =
veilid_core::deserialize_opt_json(target.into_opt_string()).unwrap(); veilid_core::deserialize_opt_json(target.into_opt_string()).unwrap();
let request: Vec<u8> = data_encoding::BASE64URL_NOPAD let request: Vec<u8> = data_encoding::BASE64URL_NOPAD
.decode( .decode(
@ -453,7 +453,7 @@ pub extern "C" fn routing_context_app_call(port: i64, id: u32, target: FfiStr, r
#[no_mangle] #[no_mangle]
pub extern "C" fn routing_context_app_message(port: i64, id: u32, target: FfiStr, message: FfiStr) { pub extern "C" fn routing_context_app_message(port: i64, id: u32, target: FfiStr, message: FfiStr) {
let target: veilid_core::DHTKey = let target: veilid_core::PublicKey =
veilid_core::deserialize_opt_json(target.into_opt_string()).unwrap(); veilid_core::deserialize_opt_json(target.into_opt_string()).unwrap();
let message: Vec<u8> = data_encoding::BASE64URL_NOPAD let message: Vec<u8> = data_encoding::BASE64URL_NOPAD
.decode( .decode(
@ -539,7 +539,7 @@ pub extern "C" fn import_remote_private_route(port: i64, blob: FfiStr) {
#[no_mangle] #[no_mangle]
pub extern "C" fn release_private_route(port: i64, key: FfiStr) { pub extern "C" fn release_private_route(port: i64, key: FfiStr) {
let key: veilid_core::DHTKey = let key: veilid_core::PublicKey =
veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap(); veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
DartIsolateWrapper::new(port).spawn_result(async move { DartIsolateWrapper::new(port).spawn_result(async move {
let veilid_api = get_veilid_api().await?; let veilid_api = get_veilid_api().await?;

View File

@ -4,7 +4,7 @@ use clap::{Arg, ArgMatches, Command};
use std::ffi::OsStr; use std::ffi::OsStr;
use std::path::Path; use std::path::Path;
use std::str::FromStr; use std::str::FromStr;
use veilid_core::{DHTKey, DHTKeySecret}; use veilid_core::{PublicKey, SecretKey};
fn do_clap_matches(default_config_path: &OsStr) -> Result<clap::ArgMatches, clap::Error> { fn do_clap_matches(default_config_path: &OsStr) -> Result<clap::ArgMatches, clap::Error> {
let matches = Command::new("veilid-server") let matches = Command::new("veilid-server")
@ -245,15 +245,16 @@ pub fn process_command_line() -> EyreResult<(Settings, ArgMatches)> {
// Split or get secret // Split or get secret
let (k, s) = if let Some((k, s)) = v.split_once(':') { let (k, s) = if let Some((k, s)) = v.split_once(':') {
let k = DHTKey::try_decode(k).wrap_err("failed to decode node id from command line")?; let k =
let s = DHTKeySecret::try_decode(s)?; PublicKey::try_decode(k).wrap_err("failed to decode node id from command line")?;
let s = SecretKey::try_decode(s)?;
(k, s) (k, s)
} else { } else {
let k = DHTKey::try_decode(v)?; let k = PublicKey::try_decode(v)?;
let buffer = rpassword::prompt_password("Enter secret key (will not echo): ") let buffer = rpassword::prompt_password("Enter secret key (will not echo): ")
.wrap_err("invalid secret key")?; .wrap_err("invalid secret key")?;
let buffer = buffer.trim().to_string(); let buffer = buffer.trim().to_string();
let s = DHTKeySecret::try_decode(&buffer)?; let s = SecretKey::try_decode(&buffer)?;
(k, s) (k, s)
}; };
settingsrw.core.network.node_id = Some(k); settingsrw.core.network.node_id = Some(k);

View File

@ -595,8 +595,8 @@ pub struct Network {
pub client_whitelist_timeout_ms: u32, pub client_whitelist_timeout_ms: u32,
pub reverse_connection_receipt_time_ms: u32, pub reverse_connection_receipt_time_ms: u32,
pub hole_punch_receipt_time_ms: u32, pub hole_punch_receipt_time_ms: u32,
pub node_id: Option<veilid_core::DHTKey>, pub node_id: Option<veilid_core::PublicKey>,
pub node_id_secret: Option<veilid_core::DHTKeySecret>, pub node_id_secret: Option<veilid_core::SecretKey>,
pub bootstrap: Vec<String>, pub bootstrap: Vec<String>,
pub bootstrap_nodes: Vec<ParsedNodeDialInfo>, pub bootstrap_nodes: Vec<ParsedNodeDialInfo>,
pub routing_table: RoutingTable, pub routing_table: RoutingTable,

View File

@ -137,7 +137,7 @@ pub struct VeilidWASMConfig {
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
pub struct VeilidKeyBlob { pub struct VeilidKeyBlob {
pub key: veilid_core::DHTKey, pub key: veilid_core::PublicKey,
#[serde(with = "veilid_core::json_as_base64")] #[serde(with = "veilid_core::json_as_base64")]
pub blob: Vec<u8>, pub blob: Vec<u8>,
} }
@ -459,7 +459,7 @@ pub fn import_remote_private_route(blob: String) -> Promise {
#[wasm_bindgen()] #[wasm_bindgen()]
pub fn release_private_route(key: String) -> Promise { pub fn release_private_route(key: String) -> Promise {
let key: veilid_core::DHTKey = veilid_core::deserialize_json(&key).unwrap(); let key: veilid_core::PublicKey = veilid_core::deserialize_json(&key).unwrap();
wrap_api_future_void(async move { wrap_api_future_void(async move {
let veilid_api = get_veilid_api()?; let veilid_api = get_veilid_api()?;
veilid_api.release_private_route(&key)?; veilid_api.release_private_route(&key)?;