mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-02-22 23:49:50 -05:00
fix tests
This commit is contained in:
parent
dfd1af0c6b
commit
ff9b421631
10
.vscode/launch.json
vendored
10
.vscode/launch.json
vendored
@ -42,16 +42,6 @@
|
|||||||
],
|
],
|
||||||
"terminal": "console"
|
"terminal": "console"
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// "type": "lldb",
|
|
||||||
// "request": "launch",
|
|
||||||
// "name": "Debug veilid-server",
|
|
||||||
// "cargo": {
|
|
||||||
// "args": ["run", "--manifest-path", "veilid-server/Cargo.toml"]
|
|
||||||
// },
|
|
||||||
// "args": ["--trace"],
|
|
||||||
// "cwd": "${workspaceFolder}/veilid-server"
|
|
||||||
// }
|
|
||||||
{
|
{
|
||||||
"type": "lldb",
|
"type": "lldb",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
|
@ -195,6 +195,7 @@ impl ClientApiConnection {
|
|||||||
|
|
||||||
let rpc_jh = spawn_local(rpc_system);
|
let rpc_jh = spawn_local(rpc_system);
|
||||||
|
|
||||||
|
let reg_res: Result<registration::Client, String> = (async {
|
||||||
// Send the request and get the state object and the registration object
|
// Send the request and get the state object and the registration object
|
||||||
let response = request
|
let response = request
|
||||||
.send()
|
.send()
|
||||||
@ -206,7 +207,7 @@ impl ClientApiConnection {
|
|||||||
.map_err(|e| format!("failed to get register response: {}", e))?;
|
.map_err(|e| format!("failed to get register response: {}", e))?;
|
||||||
|
|
||||||
// Get the registration object, which drops our connection when it is dropped
|
// Get the registration object, which drops our connection when it is dropped
|
||||||
let _registration = response
|
let registration = response
|
||||||
.get_registration()
|
.get_registration()
|
||||||
.map_err(|e| format!("failed to get registration object: {}", e))?;
|
.map_err(|e| format!("failed to get registration object: {}", e))?;
|
||||||
|
|
||||||
@ -229,11 +230,20 @@ impl ClientApiConnection {
|
|||||||
|
|
||||||
// Don't drop the registration, doing so will remove the client
|
// Don't drop the registration, doing so will remove the client
|
||||||
// object mapping from the server which we need for the update backchannel
|
// object mapping from the server which we need for the update backchannel
|
||||||
|
Ok(registration)
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let _registration = match reg_res {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
rpc_jh.abort().await;
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Wait until rpc system completion or disconnect was requested
|
// Wait until rpc system completion or disconnect was requested
|
||||||
let res = rpc_jh.await;
|
let res = rpc_jh.await;
|
||||||
// #[cfg(feature = "rt-tokio")]
|
|
||||||
// let res = res.map_err(|e| format!("join error: {}", e))?;
|
|
||||||
res.map_err(|e| format!("client RPC system error: {}", e))
|
res.map_err(|e| format!("client RPC system error: {}", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -882,16 +882,10 @@ impl UI {
|
|||||||
pub fn set_config(&mut self, config: VeilidConfigInner) {
|
pub fn set_config(&mut self, config: VeilidConfigInner) {
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
|
|
||||||
let tkv: Vec<TypedKey> = config
|
inner
|
||||||
.network
|
.ui_state
|
||||||
.routing_table
|
.node_id
|
||||||
.node_ids
|
.set(config.network.routing_table.node_id.to_string());
|
||||||
.iter()
|
|
||||||
.filter_map(|(k, v)| v.node_id.map(|nid| TypedKey::new(*k, nid)))
|
|
||||||
.collect();
|
|
||||||
let tks = TypedKeySet::from(tkv);
|
|
||||||
|
|
||||||
inner.ui_state.node_id.set(tks.to_string());
|
|
||||||
}
|
}
|
||||||
pub fn set_connection_state(&mut self, state: ConnectionState) {
|
pub fn set_connection_state(&mut self, state: ConnectionState) {
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
|
@ -20,7 +20,7 @@ pub trait CryptoSystem {
|
|||||||
key: &PublicKey,
|
key: &PublicKey,
|
||||||
secret: &SecretKey,
|
secret: &SecretKey,
|
||||||
) -> Result<SharedSecret, VeilidAPIError>;
|
) -> Result<SharedSecret, VeilidAPIError>;
|
||||||
fn generate_keypair(&self) -> (PublicKey, SecretKey);
|
fn generate_keypair(&self) -> KeyPair;
|
||||||
fn generate_hash(&self, data: &[u8]) -> PublicKey;
|
fn generate_hash(&self, data: &[u8]) -> PublicKey;
|
||||||
fn generate_hash_reader(
|
fn generate_hash_reader(
|
||||||
&self,
|
&self,
|
||||||
|
@ -117,16 +117,15 @@ impl Crypto {
|
|||||||
let mut cache_validity_key: Vec<u8> = Vec::new();
|
let mut cache_validity_key: Vec<u8> = Vec::new();
|
||||||
{
|
{
|
||||||
let c = self.unlocked_inner.config.get();
|
let c = self.unlocked_inner.config.get();
|
||||||
for ck in &VALID_CRYPTO_KINDS {
|
for ck in VALID_CRYPTO_KINDS {
|
||||||
cache_validity_key.append(
|
cache_validity_key.append(
|
||||||
&mut c
|
&mut c
|
||||||
.network
|
.network
|
||||||
.routing_table
|
.routing_table
|
||||||
.node_ids
|
.node_id
|
||||||
.get(ck)
|
.get(ck)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.node_id
|
.value
|
||||||
.unwrap()
|
|
||||||
.bytes
|
.bytes
|
||||||
.to_vec(),
|
.to_vec(),
|
||||||
);
|
);
|
||||||
@ -223,14 +222,14 @@ impl Crypto {
|
|||||||
node_ids: &[TypedKey],
|
node_ids: &[TypedKey],
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
typed_signatures: &[TypedSignature],
|
typed_signatures: &[TypedSignature],
|
||||||
) -> Result<Vec<CryptoKind>, VeilidAPIError> {
|
) -> Result<TypedKeySet, VeilidAPIError> {
|
||||||
let mut out = Vec::with_capacity(node_ids.len());
|
let mut out = TypedKeySet::with_capacity(node_ids.len());
|
||||||
for sig in typed_signatures {
|
for sig in typed_signatures {
|
||||||
for nid in node_ids {
|
for nid in node_ids {
|
||||||
if nid.kind == sig.kind {
|
if nid.kind == sig.kind {
|
||||||
if let Some(vcrypto) = self.get(sig.kind) {
|
if let Some(vcrypto) = self.get(sig.kind) {
|
||||||
vcrypto.verify(&nid.value, data, &sig.value)?;
|
vcrypto.verify(&nid.value, data, &sig.value)?;
|
||||||
out.push(nid.kind);
|
out.add(*nid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -260,6 +259,16 @@ impl Crypto {
|
|||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate keypair
|
||||||
|
/// Does not require startup/init
|
||||||
|
pub fn generate_keypair(crypto_kind: CryptoKind) -> Result<TypedKeyPair, VeilidAPIError> {
|
||||||
|
if crypto_kind == CRYPTO_KIND_VLD0 {
|
||||||
|
let kp = vld0_generate_keypair();
|
||||||
|
return Ok(TypedKeyPair::new(crypto_kind, kp));
|
||||||
|
}
|
||||||
|
Err(VeilidAPIError::generic("invalid crypto kind"))
|
||||||
|
}
|
||||||
|
|
||||||
// Internal utilities
|
// Internal utilities
|
||||||
|
|
||||||
fn cached_dh_internal<T: CryptoSystem>(
|
fn cached_dh_internal<T: CryptoSystem>(
|
||||||
|
@ -138,8 +138,8 @@ pub async fn test_no_auth(vcrypto: CryptoSystemVersion) {
|
|||||||
|
|
||||||
pub async fn test_dh(vcrypto: CryptoSystemVersion) {
|
pub async fn test_dh(vcrypto: CryptoSystemVersion) {
|
||||||
trace!("test_dh");
|
trace!("test_dh");
|
||||||
let (dht_key, dht_key_secret) = vcrypto.generate_keypair();
|
let (dht_key, dht_key_secret) = vcrypto.generate_keypair().into_split();
|
||||||
let (dht_key2, dht_key_secret2) = vcrypto.generate_keypair();
|
let (dht_key2, dht_key_secret2) = vcrypto.generate_keypair().into_split();
|
||||||
|
|
||||||
let r1 = vcrypto.compute_dh(&dht_key, &dht_key_secret2).unwrap();
|
let r1 = vcrypto.compute_dh(&dht_key, &dht_key_secret2).unwrap();
|
||||||
let r2 = vcrypto.compute_dh(&dht_key2, &dht_key_secret).unwrap();
|
let r2 = vcrypto.compute_dh(&dht_key2, &dht_key_secret).unwrap();
|
||||||
|
@ -9,8 +9,8 @@ pub async fn test_envelope_round_trip(
|
|||||||
// Create envelope
|
// Create envelope
|
||||||
let ts = Timestamp::from(0x12345678ABCDEF69u64);
|
let ts = Timestamp::from(0x12345678ABCDEF69u64);
|
||||||
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().into_split();
|
||||||
let (recipient_id, recipient_secret) = vcrypto.generate_keypair();
|
let (recipient_id, recipient_secret) = vcrypto.generate_keypair().into_split();
|
||||||
let envelope = Envelope::new(
|
let envelope = Envelope::new(
|
||||||
envelope_version,
|
envelope_version,
|
||||||
vcrypto.kind(),
|
vcrypto.kind(),
|
||||||
@ -66,7 +66,7 @@ pub async fn test_receipt_round_trip(
|
|||||||
|
|
||||||
// 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().into_split();
|
||||||
let receipt = Receipt::try_new(envelope_version, vcrypto.kind(), nonce, sender_id, body)
|
let receipt = Receipt::try_new(envelope_version, vcrypto.kind(), nonce, sender_id, body)
|
||||||
.expect("should not fail");
|
.expect("should not fail");
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ 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
|
||||||
let (dht_key, dht_key_secret) = vcrypto.generate_keypair();
|
let (dht_key, dht_key_secret) = vcrypto.generate_keypair().into_split();
|
||||||
let (dht_key2, dht_key_secret2) = vcrypto.generate_keypair();
|
let (dht_key2, dht_key_secret2) = vcrypto.generate_keypair().into_split();
|
||||||
|
|
||||||
// Verify byte patterns are different between public and secret
|
// Verify byte patterns are different between public and secret
|
||||||
assert_ne!(dht_key.bytes, dht_key_secret.bytes);
|
assert_ne!(dht_key.bytes, dht_key_secret.bytes);
|
||||||
@ -24,8 +24,8 @@ pub async fn test_generate_secret(vcrypto: CryptoSystemVersion) {
|
|||||||
|
|
||||||
pub async fn test_sign_and_verify(vcrypto: CryptoSystemVersion) {
|
pub async fn test_sign_and_verify(vcrypto: CryptoSystemVersion) {
|
||||||
// Make two keys
|
// Make two keys
|
||||||
let (dht_key, dht_key_secret) = vcrypto.generate_keypair();
|
let (dht_key, dht_key_secret) = vcrypto.generate_keypair().into_split();
|
||||||
let (dht_key2, dht_key_secret2) = vcrypto.generate_keypair();
|
let (dht_key2, dht_key_secret2) = vcrypto.generate_keypair().into_split();
|
||||||
// Sign the same message twice
|
// Sign the same message twice
|
||||||
let dht_sig = vcrypto
|
let dht_sig = vcrypto
|
||||||
.sign(&dht_key, &dht_key_secret, LOREM_IPSUM.as_bytes())
|
.sign(&dht_key, &dht_key_secret, LOREM_IPSUM.as_bytes())
|
||||||
@ -133,10 +133,10 @@ pub async fn test_key_conversions(vcrypto: CryptoSystemVersion) {
|
|||||||
assert_eq!(dht_key_secret_string, dht_key_string);
|
assert_eq!(dht_key_secret_string, dht_key_string);
|
||||||
|
|
||||||
// Make different keys
|
// Make different keys
|
||||||
let (dht_key2, dht_key_secret2) = vcrypto.generate_keypair();
|
let (dht_key2, dht_key_secret2) = vcrypto.generate_keypair().into_split();
|
||||||
trace!("dht_key2: {:?}", dht_key2);
|
trace!("dht_key2: {:?}", dht_key2);
|
||||||
trace!("dht_key_secret2: {:?}", dht_key_secret2);
|
trace!("dht_key_secret2: {:?}", dht_key_secret2);
|
||||||
let (dht_key3, _dht_key_secret3) = vcrypto.generate_keypair();
|
let (dht_key3, _dht_key_secret3) = vcrypto.generate_keypair().into_split();
|
||||||
trace!("dht_key3: {:?}", dht_key3);
|
trace!("dht_key3: {:?}", dht_key3);
|
||||||
trace!("_dht_key_secret3: {:?}", _dht_key_secret3);
|
trace!("_dht_key_secret3: {:?}", _dht_key_secret3);
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ pub async fn test_encode_decode(vcrypto: CryptoSystemVersion) {
|
|||||||
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);
|
||||||
|
|
||||||
let (dht_key2, dht_key_secret2) = vcrypto.generate_keypair();
|
let (dht_key2, dht_key_secret2) = vcrypto.generate_keypair().into_split();
|
||||||
|
|
||||||
let e1 = dht_key.encode();
|
let e1 = dht_key.encode();
|
||||||
trace!("e1: {:?}", e1);
|
trace!("e1: {:?}", e1);
|
||||||
|
@ -24,6 +24,12 @@ impl KeyPair {
|
|||||||
pub fn new(key: PublicKey, secret: SecretKey) -> Self {
|
pub fn new(key: PublicKey, secret: SecretKey) -> Self {
|
||||||
Self { key, secret }
|
Self { key, secret }
|
||||||
}
|
}
|
||||||
|
pub fn split(&self) -> (PublicKey, SecretKey) {
|
||||||
|
(self.key, self.secret)
|
||||||
|
}
|
||||||
|
pub fn into_split(self) -> (PublicKey, SecretKey) {
|
||||||
|
(self.key, self.secret)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for KeyPair {
|
impl Encodable for KeyPair {
|
||||||
|
@ -32,13 +32,13 @@ fn ed25519_to_x25519_sk(key: &ed::SecretKey) -> Result<xd::StaticSecret, VeilidA
|
|||||||
Ok(xd::StaticSecret::from(lowbytes))
|
Ok(xd::StaticSecret::from(lowbytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vld0_generate_keypair() -> (PublicKey, SecretKey) {
|
pub fn vld0_generate_keypair() -> KeyPair {
|
||||||
let mut csprng = VeilidRng {};
|
let mut csprng = VeilidRng {};
|
||||||
let keypair = ed::Keypair::generate(&mut csprng);
|
let keypair = ed::Keypair::generate(&mut csprng);
|
||||||
let dht_key = PublicKey::new(keypair.public.to_bytes());
|
let dht_key = PublicKey::new(keypair.public.to_bytes());
|
||||||
let dht_key_secret = SecretKey::new(keypair.secret.to_bytes());
|
let dht_key_secret = SecretKey::new(keypair.secret.to_bytes());
|
||||||
|
|
||||||
(dht_key, dht_key_secret)
|
KeyPair::new(dht_key, dht_key_secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// V0 CryptoSystem
|
/// V0 CryptoSystem
|
||||||
@ -95,7 +95,7 @@ impl CryptoSystem for CryptoSystemVLD0 {
|
|||||||
let sk_xd = ed25519_to_x25519_sk(&sk_ed)?;
|
let sk_xd = ed25519_to_x25519_sk(&sk_ed)?;
|
||||||
Ok(SharedSecret::new(sk_xd.diffie_hellman(&pk_xd).to_bytes()))
|
Ok(SharedSecret::new(sk_xd.diffie_hellman(&pk_xd).to_bytes()))
|
||||||
}
|
}
|
||||||
fn generate_keypair(&self) -> (PublicKey, SecretKey) {
|
fn generate_keypair(&self) -> KeyPair {
|
||||||
vld0_generate_keypair()
|
vld0_generate_keypair()
|
||||||
}
|
}
|
||||||
fn generate_hash(&self, data: &[u8]) -> PublicKey {
|
fn generate_hash(&self, data: &[u8]) -> PublicKey {
|
||||||
|
@ -527,7 +527,7 @@ impl NetworkManager {
|
|||||||
|
|
||||||
let nonce = vcrypto.random_nonce();
|
let nonce = vcrypto.random_nonce();
|
||||||
let node_id = routing_table.node_id(vcrypto.kind());
|
let node_id = routing_table.node_id(vcrypto.kind());
|
||||||
let node_id_secret = routing_table.node_id_secret(vcrypto.kind());
|
let node_id_secret = routing_table.node_id_secret_key(vcrypto.kind());
|
||||||
|
|
||||||
let receipt = Receipt::try_new(best_envelope_version(), node_id.kind, nonce, node_id.value, extra_data)?;
|
let receipt = Receipt::try_new(best_envelope_version(), node_id.kind, nonce, node_id.value, extra_data)?;
|
||||||
let out = receipt
|
let out = receipt
|
||||||
@ -556,7 +556,7 @@ impl NetworkManager {
|
|||||||
|
|
||||||
let nonce = vcrypto.random_nonce();
|
let nonce = vcrypto.random_nonce();
|
||||||
let node_id = routing_table.node_id(vcrypto.kind());
|
let node_id = routing_table.node_id(vcrypto.kind());
|
||||||
let node_id_secret = routing_table.node_id_secret(vcrypto.kind());
|
let node_id_secret = routing_table.node_id_secret_key(vcrypto.kind());
|
||||||
|
|
||||||
let receipt = Receipt::try_new(best_envelope_version(), node_id.kind, nonce, node_id.value, extra_data)?;
|
let receipt = Receipt::try_new(best_envelope_version(), node_id.kind, nonce, node_id.value, extra_data)?;
|
||||||
let out = receipt
|
let out = receipt
|
||||||
@ -754,7 +754,7 @@ impl NetworkManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let node_id = routing_table.node_id(vcrypto.kind());
|
let node_id = routing_table.node_id(vcrypto.kind());
|
||||||
let node_id_secret = routing_table.node_id_secret(vcrypto.kind());
|
let node_id_secret = routing_table.node_id_secret_key(vcrypto.kind());
|
||||||
|
|
||||||
// Get timestamp, nonce
|
// Get timestamp, nonce
|
||||||
let ts = get_aligned_timestamp();
|
let ts = get_aligned_timestamp();
|
||||||
@ -1427,7 +1427,7 @@ impl NetworkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DH to get decryption key (cached)
|
// DH to get decryption key (cached)
|
||||||
let node_id_secret = routing_table.node_id_secret(envelope.get_crypto_kind());
|
let node_id_secret = routing_table.node_id_secret_key(envelope.get_crypto_kind());
|
||||||
|
|
||||||
// Decrypt the envelope body
|
// Decrypt the envelope body
|
||||||
let body = match envelope
|
let body = match envelope
|
||||||
|
@ -72,8 +72,10 @@ pub struct RoutingTableUnlockedInner {
|
|||||||
config: VeilidConfig,
|
config: VeilidConfig,
|
||||||
network_manager: NetworkManager,
|
network_manager: NetworkManager,
|
||||||
|
|
||||||
/// The current node's public DHT keys and secrets
|
/// The current node's public DHT keys
|
||||||
node_id_keypairs: BTreeMap<CryptoKind, KeyPair>,
|
node_id: TypedKeySet,
|
||||||
|
/// The current node's public DHT secrets
|
||||||
|
node_id_secret: TypedSecretSet,
|
||||||
/// Buckets to kick on our next kick task
|
/// Buckets to kick on our next kick task
|
||||||
kick_queue: Mutex<BTreeSet<BucketIndex>>,
|
kick_queue: Mutex<BTreeSet<BucketIndex>>,
|
||||||
/// Background process for computing statistics
|
/// Background process for computing statistics
|
||||||
@ -113,33 +115,32 @@ impl RoutingTableUnlockedInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_id(&self, kind: CryptoKind) -> TypedKey {
|
pub fn node_id(&self, kind: CryptoKind) -> TypedKey {
|
||||||
TypedKey::new(kind, self.node_id_keypairs.get(&kind).unwrap().key)
|
self.node_id.get(kind).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn node_id_secret_key(&self, kind: CryptoKind) -> SecretKey {
|
||||||
|
self.node_id_secret.get(kind).unwrap().value
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_ids(&self) -> TypedKeySet {
|
pub fn node_ids(&self) -> TypedKeySet {
|
||||||
let mut tks = TypedKeySet::new();
|
self.node_id.clone()
|
||||||
for x in &self.node_id_keypairs {
|
|
||||||
tks.add(TypedKey::new(*x.0, x.1.key));
|
|
||||||
}
|
|
||||||
tks
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_id_typed_key_pairs(&self) -> Vec<TypedKeyPair> {
|
pub fn node_id_typed_key_pairs(&self) -> Vec<TypedKeyPair> {
|
||||||
let mut tkps = Vec::new();
|
let mut tkps = Vec::new();
|
||||||
for (ck, v) in &self.node_id_keypairs {
|
for ck in VALID_CRYPTO_KINDS {
|
||||||
tkps.push(TypedKeyPair::new(*ck, *v));
|
tkps.push(TypedKeyPair::new(
|
||||||
|
ck,
|
||||||
|
KeyPair::new(self.node_id(ck).value, self.node_id_secret_key(ck)),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
tkps
|
tkps
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_id_secret(&self, kind: CryptoKind) -> SecretKey {
|
|
||||||
self.node_id_keypairs.get(&kind).unwrap().secret
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn matches_own_node_id(&self, node_ids: &[TypedKey]) -> bool {
|
pub fn matches_own_node_id(&self, node_ids: &[TypedKey]) -> bool {
|
||||||
for ni in node_ids {
|
for ni in node_ids {
|
||||||
if let Some(v) = self.node_id_keypairs.get(&ni.kind) {
|
if let Some(v) = self.node_id.get(ni.kind) {
|
||||||
if v.key == ni.value {
|
if v.value == ni.value {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,8 +149,8 @@ impl RoutingTableUnlockedInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn matches_own_node_id_key(&self, node_id_key: &PublicKey) -> bool {
|
pub fn matches_own_node_id_key(&self, node_id_key: &PublicKey) -> bool {
|
||||||
for (_ck, v) in &self.node_id_keypairs {
|
for tk in self.node_id.iter() {
|
||||||
if v.key == *node_id_key {
|
if tk.value == *node_id_key {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,12 +159,12 @@ impl RoutingTableUnlockedInner {
|
|||||||
|
|
||||||
pub fn calculate_bucket_index(&self, node_id: &TypedKey) -> BucketIndex {
|
pub fn calculate_bucket_index(&self, node_id: &TypedKey) -> BucketIndex {
|
||||||
let crypto = self.crypto();
|
let crypto = self.crypto();
|
||||||
let self_node_id = self.node_id_keypairs.get(&node_id.kind).unwrap().key;
|
let self_node_id_key = self.node_id(node_id.kind).value;
|
||||||
let vcrypto = crypto.get(node_id.kind).unwrap();
|
let vcrypto = crypto.get(node_id.kind).unwrap();
|
||||||
(
|
(
|
||||||
node_id.kind,
|
node_id.kind,
|
||||||
vcrypto
|
vcrypto
|
||||||
.distance(&node_id.value, &self_node_id)
|
.distance(&node_id.value, &self_node_id_key)
|
||||||
.first_nonzero_bit()
|
.first_nonzero_bit()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
@ -182,22 +183,12 @@ impl RoutingTable {
|
|||||||
network_manager: NetworkManager,
|
network_manager: NetworkManager,
|
||||||
) -> RoutingTableUnlockedInner {
|
) -> RoutingTableUnlockedInner {
|
||||||
let c = config.get();
|
let c = config.get();
|
||||||
|
|
||||||
RoutingTableUnlockedInner {
|
RoutingTableUnlockedInner {
|
||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
network_manager,
|
network_manager,
|
||||||
node_id_keypairs: c
|
node_id: c.network.routing_table.node_id.clone(),
|
||||||
.network
|
node_id_secret: c.network.routing_table.node_id_secret.clone(),
|
||||||
.routing_table
|
|
||||||
.node_ids
|
|
||||||
.iter()
|
|
||||||
.map(|(k, v)| {
|
|
||||||
(
|
|
||||||
*k,
|
|
||||||
KeyPair::new(v.node_id.unwrap(), v.node_id_secret.unwrap()),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
|
|
||||||
kick_queue: Mutex::new(BTreeSet::default()),
|
kick_queue: Mutex::new(BTreeSet::default()),
|
||||||
rolling_transfers_task: TickTask::new(ROLLING_TRANSFERS_INTERVAL_SECS),
|
rolling_transfers_task: TickTask::new(ROLLING_TRANSFERS_INTERVAL_SECS),
|
||||||
kick_buckets_task: TickTask::new(1),
|
kick_buckets_task: TickTask::new(1),
|
||||||
|
@ -490,12 +490,12 @@ impl RouteSpecStore {
|
|||||||
let mut route_set = BTreeMap::<PublicKey, RouteSpecDetail>::new();
|
let mut route_set = BTreeMap::<PublicKey, RouteSpecDetail>::new();
|
||||||
for crypto_kind in crypto_kinds.iter().copied() {
|
for crypto_kind in crypto_kinds.iter().copied() {
|
||||||
let vcrypto = self.unlocked_inner.routing_table.crypto().get(crypto_kind).unwrap();
|
let vcrypto = self.unlocked_inner.routing_table.crypto().get(crypto_kind).unwrap();
|
||||||
let (public_key, secret_key) = vcrypto.generate_keypair();
|
let keypair = vcrypto.generate_keypair();
|
||||||
let hops: Vec<PublicKey> = route_nodes.iter().map(|v| nodes[*v].node_ids().get(crypto_kind).unwrap().value).collect();
|
let hops: Vec<PublicKey> = route_nodes.iter().map(|v| nodes[*v].node_ids().get(crypto_kind).unwrap().value).collect();
|
||||||
|
|
||||||
route_set.insert(public_key, RouteSpecDetail {
|
route_set.insert(keypair.key, RouteSpecDetail {
|
||||||
crypto_kind,
|
crypto_kind,
|
||||||
secret_key,
|
secret_key: keypair.secret,
|
||||||
hops,
|
hops,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -888,7 +888,7 @@ impl RouteSpecStore {
|
|||||||
//println!("compile_safety_route profile (stub): {} us", (get_timestamp() - profile_start_ts));
|
//println!("compile_safety_route profile (stub): {} us", (get_timestamp() - profile_start_ts));
|
||||||
return Ok(Some(CompiledRoute {
|
return Ok(Some(CompiledRoute {
|
||||||
safety_route: SafetyRoute::new_stub(routing_table.node_id(crypto_kind), private_route),
|
safety_route: SafetyRoute::new_stub(routing_table.node_id(crypto_kind), private_route),
|
||||||
secret: routing_table.node_id_secret(crypto_kind),
|
secret: routing_table.node_id_secret_key(crypto_kind),
|
||||||
first_hop,
|
first_hop,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ impl RPCProcessor {
|
|||||||
) -> 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)
|
||||||
// xxx: punish nodes that send messages that fail to decrypt eventually? How to do this for safety routes?
|
// xxx: punish nodes that send messages that fail to decrypt eventually? How to do this for safety routes?
|
||||||
let node_id_secret = self.routing_table.node_id_secret(remote_sr_pubkey.kind);
|
let node_id_secret = self.routing_table.node_id_secret_key(remote_sr_pubkey.kind);
|
||||||
let dh_secret = vcrypto
|
let dh_secret = vcrypto
|
||||||
.cached_dh(&remote_sr_pubkey.value, &node_id_secret)
|
.cached_dh(&remote_sr_pubkey.value, &node_id_secret)
|
||||||
.map_err(RPCError::protocol)?;
|
.map_err(RPCError::protocol)?;
|
||||||
@ -313,7 +313,7 @@ impl RPCProcessor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 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(crypto_kind);
|
let node_id_secret = self.routing_table.node_id_secret_key(crypto_kind);
|
||||||
let dh_secret = vcrypto
|
let dh_secret = vcrypto
|
||||||
.cached_dh(&pr_pubkey.value, &node_id_secret)
|
.cached_dh(&pr_pubkey.value, &node_id_secret)
|
||||||
.map_err(RPCError::protocol)?;
|
.map_err(RPCError::protocol)?;
|
||||||
@ -345,7 +345,7 @@ impl RPCProcessor {
|
|||||||
// as the last hop is already signed by the envelope
|
// as the last hop is already signed by the envelope
|
||||||
if route_hop.next_hop.is_some() {
|
if route_hop.next_hop.is_some() {
|
||||||
let node_id = self.routing_table.node_id(crypto_kind);
|
let node_id = self.routing_table.node_id(crypto_kind);
|
||||||
let node_id_secret = self.routing_table.node_id_secret(crypto_kind);
|
let node_id_secret = self.routing_table.node_id_secret_key(crypto_kind);
|
||||||
let sig = vcrypto
|
let sig = vcrypto
|
||||||
.sign(&node_id.value, &node_id_secret, &route_operation.data)
|
.sign(&node_id.value, &node_id_secret, &route_operation.data)
|
||||||
.map_err(RPCError::internal)?;
|
.map_err(RPCError::internal)?;
|
||||||
@ -392,7 +392,7 @@ impl RPCProcessor {
|
|||||||
// There is a safety route hop
|
// There is a safety route hop
|
||||||
SafetyRouteHops::Data(ref route_hop_data) => {
|
SafetyRouteHops::Data(ref route_hop_data) => {
|
||||||
// Decrypt the blob with DEC(nonce, DH(the SR's public key, this hop's secret)
|
// Decrypt the blob with DEC(nonce, DH(the SR's public key, this hop's secret)
|
||||||
let node_id_secret = self.routing_table.node_id_secret(crypto_kind);
|
let node_id_secret = self.routing_table.node_id_secret_key(crypto_kind);
|
||||||
let dh_secret = vcrypto
|
let dh_secret = vcrypto
|
||||||
.cached_dh(&route.safety_route.public_key.value, &node_id_secret)
|
.cached_dh(&route.safety_route.public_key.value, &node_id_secret)
|
||||||
.map_err(RPCError::protocol)?;
|
.map_err(RPCError::protocol)?;
|
||||||
|
@ -128,19 +128,19 @@ pub async fn test_frozen(vcrypto: CryptoSystemVersion, ts: TableStore) {
|
|||||||
|
|
||||||
let _ = ts.delete("test");
|
let _ = ts.delete("test");
|
||||||
let db = ts.open("test", 3).await.expect("should have opened");
|
let db = ts.open("test", 3).await.expect("should have opened");
|
||||||
let (dht_key, _) = vcrypto.generate_keypair();
|
let keypair = vcrypto.generate_keypair();
|
||||||
|
|
||||||
assert!(db.store_rkyv(0, b"asdf", &dht_key).await.is_ok());
|
assert!(db.store_rkyv(0, b"asdf", &keypair).await.is_ok());
|
||||||
|
|
||||||
assert_eq!(db.load_rkyv::<PublicKey>(0, b"qwer").unwrap(), None);
|
assert_eq!(db.load_rkyv::<KeyPair>(0, b"qwer").unwrap(), None);
|
||||||
|
|
||||||
let d = match db.load_rkyv::<PublicKey>(0, b"asdf") {
|
let d = match db.load_rkyv::<KeyPair>(0, b"asdf") {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
panic!("couldn't decode: {}", e);
|
panic!("couldn't decode: {}", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
assert_eq!(d, Some(dht_key), "keys should be equal");
|
assert_eq!(d, Some(keypair), "keys should be equal");
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
db.store(1, b"foo", b"1234567890").await.is_ok(),
|
db.store(1, b"foo", b"1234567890").await.is_ok(),
|
||||||
|
@ -320,7 +320,8 @@ pub async fn test_config() {
|
|||||||
assert_eq!(inner.network.rpc.timeout_ms, 10_000u32);
|
assert_eq!(inner.network.rpc.timeout_ms, 10_000u32);
|
||||||
assert_eq!(inner.network.rpc.max_route_hop_count, 4u8);
|
assert_eq!(inner.network.rpc.max_route_hop_count, 4u8);
|
||||||
assert_eq!(inner.network.rpc.default_route_hop_count, 1u8);
|
assert_eq!(inner.network.rpc.default_route_hop_count, 1u8);
|
||||||
assert_eq!(inner.network.routing_table.node_ids.len(), 0);
|
assert_eq!(inner.network.routing_table.node_id.len(), 0);
|
||||||
|
assert_eq!(inner.network.routing_table.node_id_secret.len(), 0);
|
||||||
assert_eq!(inner.network.routing_table.bootstrap, Vec::<String>::new());
|
assert_eq!(inner.network.routing_table.bootstrap, Vec::<String>::new());
|
||||||
assert_eq!(inner.network.routing_table.limit_over_attached, 64u32);
|
assert_eq!(inner.network.routing_table.limit_over_attached, 64u32);
|
||||||
assert_eq!(inner.network.routing_table.limit_fully_attached, 32u32);
|
assert_eq!(inner.network.routing_table.limit_fully_attached, 32u32);
|
||||||
|
@ -67,15 +67,15 @@ pub async fn test_signed_node_info() {
|
|||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
|
|
||||||
let (pkey, skey) = vcrypto.generate_keypair();
|
// Test correct validation
|
||||||
|
let keypair = vcrypto.generate_keypair();
|
||||||
let sni = SignedDirectNodeInfo::make_signatures(
|
let sni = SignedDirectNodeInfo::make_signatures(
|
||||||
crypto.clone(),
|
crypto.clone(),
|
||||||
vec![TypedKeyPair::new(ck, KeyPair::new(pkey, skey))],
|
vec![TypedKeyPair::new(ck, keypair)],
|
||||||
node_info.clone(),
|
node_info.clone(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut tks: TypedKeySet = TypedKey::new(ck, pkey).into();
|
let mut tks: TypedKeySet = TypedKey::new(ck, keypair.key).into();
|
||||||
let oldtkslen = tks.len();
|
let oldtkslen = tks.len();
|
||||||
let _ = SignedDirectNodeInfo::new(
|
let _ = SignedDirectNodeInfo::new(
|
||||||
crypto.clone(),
|
crypto.clone(),
|
||||||
@ -88,6 +88,38 @@ pub async fn test_signed_node_info() {
|
|||||||
assert_eq!(tks.len(), oldtkslen);
|
assert_eq!(tks.len(), oldtkslen);
|
||||||
assert_eq!(tks.len(), sni.signatures.len());
|
assert_eq!(tks.len(), sni.signatures.len());
|
||||||
|
|
||||||
|
// Test incorrect validation
|
||||||
|
let keypair1 = vcrypto.generate_keypair();
|
||||||
|
let mut tks1: TypedKeySet = TypedKey::new(ck, keypair1.key).into();
|
||||||
|
let oldtks1len = tks1.len();
|
||||||
|
let _ = SignedDirectNodeInfo::new(
|
||||||
|
crypto.clone(),
|
||||||
|
&mut tks1,
|
||||||
|
node_info.clone(),
|
||||||
|
sni.timestamp,
|
||||||
|
sni.signatures.clone(),
|
||||||
|
)
|
||||||
|
.unwrap_err();
|
||||||
|
assert_eq!(tks1.len(), oldtks1len);
|
||||||
|
assert_eq!(tks1.len(), sni.signatures.len());
|
||||||
|
|
||||||
|
// Test unsupported cryptosystem validation
|
||||||
|
let fake_crypto_kind: CryptoKind = FourCC::from([0, 1, 2, 3]);
|
||||||
|
let mut tksfake: TypedKeySet = TypedKey::new(fake_crypto_kind, PublicKey::default()).into();
|
||||||
|
let mut sigsfake = sni.signatures.clone();
|
||||||
|
sigsfake.push(TypedSignature::new(fake_crypto_kind, Signature::default()));
|
||||||
|
tksfake.add(TypedKey::new(ck, keypair.key));
|
||||||
|
let sdnifake = SignedDirectNodeInfo::new(
|
||||||
|
crypto.clone(),
|
||||||
|
&mut tksfake,
|
||||||
|
node_info.clone(),
|
||||||
|
sni.timestamp,
|
||||||
|
sigsfake.clone(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(tksfake.len(), 1);
|
||||||
|
assert_eq!(sdnifake.signatures.len(), sigsfake.len());
|
||||||
|
|
||||||
// Test relayed
|
// Test relayed
|
||||||
let node_info2 = NodeInfo {
|
let node_info2 = NodeInfo {
|
||||||
network_class: NetworkClass::OutboundOnly,
|
network_class: NetworkClass::OutboundOnly,
|
||||||
@ -101,13 +133,14 @@ pub async fn test_signed_node_info() {
|
|||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
|
|
||||||
let (pkey2, skey2) = vcrypto.generate_keypair();
|
// Test correct validation
|
||||||
let mut tks2: TypedKeySet = TypedKey::new(ck, pkey2).into();
|
let keypair2 = vcrypto.generate_keypair();
|
||||||
|
let mut tks2: TypedKeySet = TypedKey::new(ck, keypair2.key).into();
|
||||||
let oldtks2len = tks2.len();
|
let oldtks2len = tks2.len();
|
||||||
|
|
||||||
let sni2 = SignedRelayedNodeInfo::make_signatures(
|
let sni2 = SignedRelayedNodeInfo::make_signatures(
|
||||||
crypto.clone(),
|
crypto.clone(),
|
||||||
vec![TypedKeyPair::new(ck, KeyPair::new(pkey2, skey2))],
|
vec![TypedKeyPair::new(ck, keypair2)],
|
||||||
node_info2.clone(),
|
node_info2.clone(),
|
||||||
tks.clone(),
|
tks.clone(),
|
||||||
sni.clone(),
|
sni.clone(),
|
||||||
@ -116,9 +149,9 @@ pub async fn test_signed_node_info() {
|
|||||||
let _ = SignedRelayedNodeInfo::new(
|
let _ = SignedRelayedNodeInfo::new(
|
||||||
crypto.clone(),
|
crypto.clone(),
|
||||||
&mut tks2,
|
&mut tks2,
|
||||||
node_info2,
|
node_info2.clone(),
|
||||||
tks,
|
tks.clone(),
|
||||||
sni,
|
sni.clone(),
|
||||||
sni2.timestamp,
|
sni2.timestamp,
|
||||||
sni2.signatures.clone(),
|
sni2.signatures.clone(),
|
||||||
)
|
)
|
||||||
@ -126,6 +159,45 @@ pub async fn test_signed_node_info() {
|
|||||||
|
|
||||||
assert_eq!(tks2.len(), oldtks2len);
|
assert_eq!(tks2.len(), oldtks2len);
|
||||||
assert_eq!(tks2.len(), sni2.signatures.len());
|
assert_eq!(tks2.len(), sni2.signatures.len());
|
||||||
|
|
||||||
|
// Test incorrect validation
|
||||||
|
let keypair3 = vcrypto.generate_keypair();
|
||||||
|
let mut tks3: TypedKeySet = TypedKey::new(ck, keypair3.key).into();
|
||||||
|
let oldtks3len = tks3.len();
|
||||||
|
|
||||||
|
let _ = SignedRelayedNodeInfo::new(
|
||||||
|
crypto.clone(),
|
||||||
|
&mut tks3,
|
||||||
|
node_info2.clone(),
|
||||||
|
tks.clone(),
|
||||||
|
sni.clone(),
|
||||||
|
sni2.timestamp,
|
||||||
|
sni2.signatures.clone(),
|
||||||
|
)
|
||||||
|
.unwrap_err();
|
||||||
|
|
||||||
|
assert_eq!(tks3.len(), oldtks3len);
|
||||||
|
assert_eq!(tks3.len(), sni2.signatures.len());
|
||||||
|
|
||||||
|
// Test unsupported cryptosystem validation
|
||||||
|
let fake_crypto_kind: CryptoKind = FourCC::from([0, 1, 2, 3]);
|
||||||
|
let mut tksfake3: TypedKeySet =
|
||||||
|
TypedKey::new(fake_crypto_kind, PublicKey::default()).into();
|
||||||
|
let mut sigsfake3 = sni2.signatures.clone();
|
||||||
|
sigsfake3.push(TypedSignature::new(fake_crypto_kind, Signature::default()));
|
||||||
|
tksfake3.add(TypedKey::new(ck, keypair2.key));
|
||||||
|
let srnifake = SignedRelayedNodeInfo::new(
|
||||||
|
crypto.clone(),
|
||||||
|
&mut tksfake3,
|
||||||
|
node_info2.clone(),
|
||||||
|
tks.clone(),
|
||||||
|
sni.clone(),
|
||||||
|
sni2.timestamp,
|
||||||
|
sigsfake3.clone(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(tksfake3.len(), 1);
|
||||||
|
assert_eq!(srnifake.signatures.len(), sigsfake3.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
api.shutdown().await;
|
api.shutdown().await;
|
||||||
|
@ -1869,7 +1869,8 @@ pub struct SignedDirectNodeInfo {
|
|||||||
pub signatures: Vec<TypedSignature>,
|
pub signatures: Vec<TypedSignature>,
|
||||||
}
|
}
|
||||||
impl SignedDirectNodeInfo {
|
impl SignedDirectNodeInfo {
|
||||||
/// Returns a new SignedDirectNodeInfo that has its signatures validated. Will modify the node_ids set to only include node_ids whose signatures validate
|
/// Returns a new SignedDirectNodeInfo that has its signatures validated.
|
||||||
|
/// On success, this will modify the node_ids set to only include node_ids whose signatures validate.
|
||||||
/// All signatures are stored however, as this can be passed to other nodes that may be able to validate those signatures.
|
/// All signatures are stored however, as this can be passed to other nodes that may be able to validate those signatures.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
crypto: Crypto,
|
crypto: Crypto,
|
||||||
@ -1881,9 +1882,9 @@ impl SignedDirectNodeInfo {
|
|||||||
let node_info_bytes = Self::make_signature_bytes(&node_info, timestamp)?;
|
let node_info_bytes = Self::make_signature_bytes(&node_info, timestamp)?;
|
||||||
|
|
||||||
// Verify the signatures that we can
|
// Verify the signatures that we can
|
||||||
let valid_crypto_kinds =
|
let validated_node_ids =
|
||||||
crypto.verify_signatures(node_ids, &node_info_bytes, &typed_signatures)?;
|
crypto.verify_signatures(node_ids, &node_info_bytes, &typed_signatures)?;
|
||||||
xx wrong! should remove only the kinds that are not valid! also fix relayed node_ids.remove_all(&valid_crypto_kinds);
|
*node_ids = validated_node_ids;
|
||||||
if node_ids.len() == 0 {
|
if node_ids.len() == 0 {
|
||||||
apibail_generic!("no valid node ids in direct node info");
|
apibail_generic!("no valid node ids in direct node info");
|
||||||
}
|
}
|
||||||
@ -1956,7 +1957,8 @@ pub struct SignedRelayedNodeInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SignedRelayedNodeInfo {
|
impl SignedRelayedNodeInfo {
|
||||||
/// Returns a new SignedRelayedNodeInfo that has its signatures validated. Will modify the node_ids set to only include node_ids whose signatures validate
|
/// Returns a new SignedRelayedNodeInfo that has its signatures validated.
|
||||||
|
/// On success, this will modify the node_ids set to only include node_ids whose signatures validate.
|
||||||
/// All signatures are stored however, as this can be passed to other nodes that may be able to validate those signatures.
|
/// All signatures are stored however, as this can be passed to other nodes that may be able to validate those signatures.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
crypto: Crypto,
|
crypto: Crypto,
|
||||||
@ -1969,10 +1971,9 @@ impl SignedRelayedNodeInfo {
|
|||||||
) -> Result<Self, VeilidAPIError> {
|
) -> Result<Self, VeilidAPIError> {
|
||||||
let node_info_bytes =
|
let node_info_bytes =
|
||||||
Self::make_signature_bytes(&node_info, &relay_ids, &relay_info, timestamp)?;
|
Self::make_signature_bytes(&node_info, &relay_ids, &relay_info, timestamp)?;
|
||||||
let valid_crypto_kinds =
|
let validated_node_ids =
|
||||||
crypto.verify_signatures(node_ids, &node_info_bytes, &typed_signatures)?;
|
crypto.verify_signatures(node_ids, &node_info_bytes, &typed_signatures)?;
|
||||||
|
*node_ids = validated_node_ids;
|
||||||
node_ids.remove_all(&valid_crypto_kinds);
|
|
||||||
if node_ids.len() == 0 {
|
if node_ids.len() == 0 {
|
||||||
apibail_generic!("no valid node ids in relayed node info");
|
apibail_generic!("no valid node ids in relayed node info");
|
||||||
}
|
}
|
||||||
|
@ -316,25 +316,6 @@ 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(
|
||||||
@ -350,7 +331,8 @@ pub struct VeilidConfigNodeId {
|
|||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
)]
|
)]
|
||||||
pub struct VeilidConfigRoutingTable {
|
pub struct VeilidConfigRoutingTable {
|
||||||
pub node_ids: BTreeMap<CryptoKind, VeilidConfigNodeId>,
|
pub node_id: TypedKeySet,
|
||||||
|
pub node_id_secret: TypedSecretSet,
|
||||||
pub bootstrap: Vec<String>,
|
pub bootstrap: Vec<String>,
|
||||||
pub limit_over_attached: u32,
|
pub limit_over_attached: u32,
|
||||||
pub limit_fully_attached: u32,
|
pub limit_fully_attached: u32,
|
||||||
@ -621,58 +603,15 @@ impl VeilidConfig {
|
|||||||
let keyname = &stringify!($key)[6..];
|
let keyname = &stringify!($key)[6..];
|
||||||
let v = cb(keyname.to_owned())?;
|
let v = cb(keyname.to_owned())?;
|
||||||
$key = match v.downcast() {
|
$key = match v.downcast() {
|
||||||
Ok(v) => *v,
|
|
||||||
Err(e) => {
|
|
||||||
apibail_generic!(format!("incorrect type for key {}: {:?}", keyname, type_name_of_val(&*e)))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// More complicated optional fields for node ids
|
|
||||||
macro_rules! get_config_node_ids {
|
|
||||||
() => {
|
|
||||||
let keys = cb("network.routing_table.node_id".to_owned())?;
|
|
||||||
let keys: TypedKeySet = match keys.downcast() {
|
|
||||||
Ok(v) => *v,
|
Ok(v) => *v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
apibail_generic!(format!(
|
apibail_generic!(format!(
|
||||||
"incorrect type for key 'network.routing_table.node_id': {:?}",
|
"incorrect type for key {}: {:?}",
|
||||||
|
keyname,
|
||||||
type_name_of_val(&*e)
|
type_name_of_val(&*e)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let secrets = cb("network.routing_table.node_id_secret".to_owned())?;
|
|
||||||
let secrets: TypedSecretSet = match secrets.downcast() {
|
|
||||||
Ok(v) => *v,
|
|
||||||
Err(e) => {
|
|
||||||
apibail_generic!(format!(
|
|
||||||
"incorrect type for key 'network.routing_table.node_id_secret': {:?}",
|
|
||||||
type_name_of_val(&*e)
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for ck in VALID_CRYPTO_KINDS {
|
|
||||||
if let Some(key) = keys.get(ck) {
|
|
||||||
inner
|
|
||||||
.network
|
|
||||||
.routing_table
|
|
||||||
.node_ids
|
|
||||||
.entry(ck)
|
|
||||||
.or_default()
|
|
||||||
.node_id = Some(key.value);
|
|
||||||
}
|
|
||||||
if let Some(secret) = secrets.get(ck) {
|
|
||||||
inner
|
|
||||||
.network
|
|
||||||
.routing_table
|
|
||||||
.node_ids
|
|
||||||
.entry(ck)
|
|
||||||
.or_default()
|
|
||||||
.node_id_secret = Some(secret.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -701,7 +640,9 @@ impl VeilidConfig {
|
|||||||
get_config!(inner.network.max_connection_frequency_per_min);
|
get_config!(inner.network.max_connection_frequency_per_min);
|
||||||
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_node_ids!();
|
get_config!(inner.network.hole_punch_receipt_time_ms);
|
||||||
|
get_config!(inner.network.routing_table.node_id);
|
||||||
|
get_config!(inner.network.routing_table.node_id_secret);
|
||||||
get_config!(inner.network.routing_table.bootstrap);
|
get_config!(inner.network.routing_table.bootstrap);
|
||||||
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);
|
||||||
@ -778,11 +719,20 @@ impl VeilidConfig {
|
|||||||
self.inner.read()
|
self.inner.read()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn safe_config(&self) -> VeilidConfigInner {
|
||||||
|
let mut safe_cfg = self.inner.read().clone();
|
||||||
|
|
||||||
|
// Remove secrets
|
||||||
|
safe_cfg.network.routing_table.node_id_secret = TypedSecretSet::new();
|
||||||
|
|
||||||
|
safe_cfg
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_mut<F, R>(&self, f: F) -> Result<R, VeilidAPIError>
|
pub fn with_mut<F, R>(&self, f: F) -> Result<R, VeilidAPIError>
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut VeilidConfigInner) -> Result<R, VeilidAPIError>,
|
F: FnOnce(&mut VeilidConfigInner) -> Result<R, VeilidAPIError>,
|
||||||
{
|
{
|
||||||
let (out, config) = {
|
let out = {
|
||||||
let inner = &mut *self.inner.write();
|
let inner = &mut *self.inner.write();
|
||||||
// Edit a copy
|
// Edit a copy
|
||||||
let mut editedinner = inner.clone();
|
let mut editedinner = inner.clone();
|
||||||
@ -792,12 +742,13 @@ impl VeilidConfig {
|
|||||||
Self::validate(&mut editedinner)?;
|
Self::validate(&mut editedinner)?;
|
||||||
// Commit changes
|
// Commit changes
|
||||||
*inner = editedinner.clone();
|
*inner = editedinner.clone();
|
||||||
(out, editedinner)
|
out
|
||||||
};
|
};
|
||||||
|
|
||||||
// Send configuration update to clients
|
// Send configuration update to clients
|
||||||
if let Some(update_cb) = &self.update_cb {
|
if let Some(update_cb) = &self.update_cb {
|
||||||
update_cb(VeilidUpdate::Config(VeilidStateConfig { config }));
|
let safe_cfg = self.safe_config();
|
||||||
|
update_cb(VeilidUpdate::Config(VeilidStateConfig { config: safe_cfg }));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(out)
|
Ok(out)
|
||||||
@ -975,29 +926,23 @@ impl VeilidConfig {
|
|||||||
crypto: Crypto,
|
crypto: Crypto,
|
||||||
protected_store: intf::ProtectedStore,
|
protected_store: intf::ProtectedStore,
|
||||||
) -> Result<(), VeilidAPIError> {
|
) -> Result<(), VeilidAPIError> {
|
||||||
|
let mut out_node_id = TypedKeySet::new();
|
||||||
|
let mut out_node_id_secret = TypedSecretSet::new();
|
||||||
|
|
||||||
for ck in VALID_CRYPTO_KINDS {
|
for ck in VALID_CRYPTO_KINDS {
|
||||||
let vcrypto = crypto
|
let vcrypto = crypto
|
||||||
.get(ck)
|
.get(ck)
|
||||||
.expect("Valid crypto kind is not actually valid.");
|
.expect("Valid crypto kind is not actually valid.");
|
||||||
|
|
||||||
let mut node_id = self
|
let mut node_id = self.inner.read().network.routing_table.node_id.get(ck);
|
||||||
.inner
|
|
||||||
.read()
|
|
||||||
.network
|
|
||||||
.routing_table
|
|
||||||
.node_ids
|
|
||||||
.get(&ck)
|
|
||||||
.map(|n| n.node_id)
|
|
||||||
.flatten();
|
|
||||||
let mut node_id_secret = self
|
let mut node_id_secret = self
|
||||||
.inner
|
.inner
|
||||||
.read()
|
.read()
|
||||||
.network
|
.network
|
||||||
.routing_table
|
.routing_table
|
||||||
.node_ids
|
.node_id_secret
|
||||||
.get(&ck)
|
.get(ck);
|
||||||
.map(|n| n.node_id_secret)
|
|
||||||
.flatten();
|
|
||||||
// See if node id was previously stored in the protected store
|
// See if node id was previously stored in the protected store
|
||||||
if node_id.is_none() {
|
if node_id.is_none() {
|
||||||
debug!("pulling node_id_{} from storage", ck);
|
debug!("pulling node_id_{} from storage", ck);
|
||||||
@ -1007,8 +952,13 @@ impl VeilidConfig {
|
|||||||
.map_err(VeilidAPIError::internal)?
|
.map_err(VeilidAPIError::internal)?
|
||||||
{
|
{
|
||||||
debug!("node_id_{} found in storage", ck);
|
debug!("node_id_{} found in storage", ck);
|
||||||
node_id =
|
node_id = match TypedKey::from_str(s.as_str()) {
|
||||||
Some(PublicKey::try_decode(s.as_str()).map_err(VeilidAPIError::internal)?);
|
Ok(v) => Some(v),
|
||||||
|
Err(_) => {
|
||||||
|
debug!("node id in protected store is not valid");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
debug!("node_id_{} not found in storage", ck);
|
debug!("node_id_{} not found in storage", ck);
|
||||||
}
|
}
|
||||||
@ -1023,8 +973,13 @@ impl VeilidConfig {
|
|||||||
.map_err(VeilidAPIError::internal)?
|
.map_err(VeilidAPIError::internal)?
|
||||||
{
|
{
|
||||||
debug!("node_id_secret_{} found in storage", ck);
|
debug!("node_id_secret_{} found in storage", ck);
|
||||||
node_id_secret =
|
node_id_secret = match TypedSecret::from_str(s.as_str()) {
|
||||||
Some(SecretKey::try_decode(s.as_str()).map_err(VeilidAPIError::internal)?);
|
Ok(v) => Some(v),
|
||||||
|
Err(_) => {
|
||||||
|
debug!("node id secret in protected store is not valid");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
debug!("node_id_secret_{} not found in storage", ck);
|
debug!("node_id_secret_{} not found in storage", ck);
|
||||||
}
|
}
|
||||||
@ -1034,7 +989,7 @@ impl VeilidConfig {
|
|||||||
let (node_id, node_id_secret) =
|
let (node_id, node_id_secret) =
|
||||||
if let (Some(node_id), Some(node_id_secret)) = (node_id, node_id_secret) {
|
if let (Some(node_id), Some(node_id_secret)) = (node_id, node_id_secret) {
|
||||||
// Validate node id
|
// Validate node id
|
||||||
if !vcrypto.validate_keypair(&node_id, &node_id_secret) {
|
if !vcrypto.validate_keypair(&node_id.value, &node_id_secret.value) {
|
||||||
apibail_generic!(format!(
|
apibail_generic!(format!(
|
||||||
"node_id_secret_{} and node_id_key_{} don't match",
|
"node_id_secret_{} and node_id_key_{} don't match",
|
||||||
ck, ck
|
ck, ck
|
||||||
@ -1044,30 +999,36 @@ impl VeilidConfig {
|
|||||||
} else {
|
} else {
|
||||||
// If we still don't have a valid node id, generate one
|
// If we still don't have a valid node id, generate one
|
||||||
debug!("generating new node_id_{}", ck);
|
debug!("generating new node_id_{}", ck);
|
||||||
vcrypto.generate_keypair()
|
let kp = vcrypto.generate_keypair();
|
||||||
|
(TypedKey::new(ck, kp.key), TypedSecret::new(ck, kp.secret))
|
||||||
};
|
};
|
||||||
info!("Node Id ({}) is {}", ck, node_id.encode());
|
info!("Node Id: {}", node_id);
|
||||||
|
|
||||||
// Save the node id / secret in storage
|
// Save the node id / secret in storage
|
||||||
protected_store
|
protected_store
|
||||||
.save_user_secret_string(format!("node_id_{}", ck), node_id.encode().as_str())
|
.save_user_secret_string(format!("node_id_{}", ck), node_id.to_string())
|
||||||
.await
|
.await
|
||||||
.map_err(VeilidAPIError::internal)?;
|
.map_err(VeilidAPIError::internal)?;
|
||||||
protected_store
|
protected_store
|
||||||
.save_user_secret_string(
|
.save_user_secret_string(
|
||||||
format!("node_id_secret_{}", ck),
|
format!("node_id_secret_{}", ck),
|
||||||
node_id_secret.encode().as_str(),
|
node_id_secret.to_string(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(VeilidAPIError::internal)?;
|
.map_err(VeilidAPIError::internal)?;
|
||||||
|
|
||||||
|
// Save for config
|
||||||
|
out_node_id.add(node_id);
|
||||||
|
out_node_id_secret.add(node_id_secret);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit back to config
|
||||||
self.with_mut(|c| {
|
self.with_mut(|c| {
|
||||||
let n = c.network.routing_table.node_ids.entry(ck).or_default();
|
c.network.routing_table.node_id = out_node_id;
|
||||||
n.node_id = Some(node_id);
|
c.network.routing_table.node_id_secret = out_node_id_secret;
|
||||||
n.node_id_secret = Some(node_id_secret);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
}
|
|
||||||
trace!("init_node_ids complete");
|
trace!("init_node_ids complete");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -18,9 +18,9 @@ use cfg_if::*;
|
|||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use color_eyre::eyre::{bail, ensure, eyre, Result as EyreResult, WrapErr};
|
use color_eyre::eyre::{bail, ensure, eyre, Result as EyreResult, WrapErr};
|
||||||
use server::*;
|
use server::*;
|
||||||
|
use std::str::FromStr;
|
||||||
use tools::*;
|
use tools::*;
|
||||||
use tracing::*;
|
use tracing::*;
|
||||||
use veilid_core::Encodable as _;
|
|
||||||
use veilid_logs::*;
|
use veilid_logs::*;
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
@ -44,9 +44,15 @@ fn main() -> EyreResult<()> {
|
|||||||
|
|
||||||
// --- Generate DHT Key ---
|
// --- Generate DHT Key ---
|
||||||
if matches.occurrences_of("generate-key-pair") != 0 {
|
if matches.occurrences_of("generate-key-pair") != 0 {
|
||||||
let (key, secret) = veilid_core::vld0_generate_keypair();
|
if let Some(ckstr) = matches.get_one::<String>("generate-key-pair") {
|
||||||
println!("Public: {}\nSecret: {}", key.encode(), secret.encode());
|
let ck: veilid_core::CryptoKind =
|
||||||
|
veilid_core::FourCC::from_str(ckstr).wrap_err("couldn't parse crypto kind")?;
|
||||||
|
let tkp = veilid_core::Crypto::generate_keypair(ck).wrap_err("invalid crypto kind")?;
|
||||||
|
println!("{}", tkp.to_string());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
} else {
|
||||||
|
bail!("missing crypto kind");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we're just running a quick command
|
// See if we're just running a quick command
|
||||||
|
@ -37,9 +37,14 @@ fn init_callbacks() {
|
|||||||
case "capabilities.protocol_connect_wss": return true;
|
case "capabilities.protocol_connect_wss": return true;
|
||||||
case "capabilities.protocol_accept_wss": return false;
|
case "capabilities.protocol_accept_wss": return false;
|
||||||
case "tablestore.directory": return "";
|
case "tablestore.directory": return "";
|
||||||
case "network.node_id": return "ZLd4uMYdP4qYLtxF6GqrzBb32Z6T3rE2FWMkWup1pdY";
|
case "network.routing_table.node_id": return [];
|
||||||
case "network.node_id_secret": return "s2Gvq6HJOxgQh-3xIgfWSL3I-DWZ2c1RjZLJl2Xmg2E";
|
case "network.routing_table.node_id_secret": return [];
|
||||||
case "network.bootstrap": return [];
|
case "network.routing_table.bootstrap": return [];
|
||||||
|
case "network.routing_table.limit_over_attached": return 64;
|
||||||
|
case "network.routing_table.limit_fully_attached": return 32;
|
||||||
|
case "network.routing_table.limit_attached_strong": return 16;
|
||||||
|
case "network.routing_table.limit_attached_good": return 8;
|
||||||
|
case "network.routing_table.limit_attached_weak": return 4;
|
||||||
case "network.rpc.concurrency": return 2;
|
case "network.rpc.concurrency": return 2;
|
||||||
case "network.rpc.queue_size": return 128;
|
case "network.rpc.queue_size": return 128;
|
||||||
case "network.rpc.max_timestamp_behind": return 10000000;
|
case "network.rpc.max_timestamp_behind": return 10000000;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user