This commit is contained in:
John Smith
2023-03-01 15:50:30 -05:00
parent 615158d54e
commit 562f9bb7f7
36 changed files with 943 additions and 784 deletions
+37 -37
View File
@@ -44,17 +44,29 @@ pub const SHARED_SECRET_LENGTH_ENCODED: usize = 43;
/// Length of a route id in bytes
#[allow(dead_code)]
pub const ROUTE_ID_LENGTH: usize = 32;
/// Length of a route id in bytes afer encoding to base64url
#[allow(dead_code)]
pub const ROUTE_ID_LENGTH_ENCODED: usize = 43;
//////////////////////////////////////////////////////////////////////
pub trait Encodable {
pub trait Encodable
where
Self: Sized,
{
fn encode(&self) -> String;
fn encoded_len() -> usize;
fn try_decode<S: AsRef<str>>(input: S) -> Result<Self, VeilidAPIError> {
let b = input.as_ref().as_bytes();
Self::try_decode_bytes(b)
}
fn try_decode_bytes(b: &[u8]) -> Result<Self, VeilidAPIError>;
}
//////////////////////////////////////////////////////////////////////
macro_rules! byte_array_type {
($name:ident, $size:expr) => {
($name:ident, $size:expr, $encoded_size:expr) => {
#[derive(
Clone,
Copy,
@@ -161,12 +173,16 @@ macro_rules! byte_array_type {
}
None
}
}
pub fn try_decode<S: AsRef<str>>(input: S) -> Result<Self, VeilidAPIError> {
let b = input.as_ref().as_bytes();
Self::try_decode_bytes(b)
impl Encodable for $name {
fn encode(&self) -> String {
BASE64URL_NOPAD.encode(&self.bytes)
}
pub fn try_decode_bytes(b: &[u8]) -> Result<Self, VeilidAPIError> {
fn encoded_len() -> usize {
$encoded_size
}
fn try_decode_bytes(b: &[u8]) -> Result<Self, VeilidAPIError> {
let mut bytes = [0u8; $size];
let res = BASE64URL_NOPAD.decode_len(b.len());
match res {
@@ -187,15 +203,8 @@ macro_rules! byte_array_type {
}
}
}
impl Encodable for $name {
fn encode(&self) -> String {
BASE64URL_NOPAD.encode(&self.bytes)
}
}
impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
//write!(f, "{}", String::from(self))
write!(f, "{}", self.encode())
}
}
@@ -210,12 +219,6 @@ macro_rules! byte_array_type {
impl From<&$name> for String {
fn from(value: &$name) -> Self {
// let mut s = String::new();
// for n in 0..($size / 8) {
// let b: [u8; 8] = value.bytes[n * 8..(n + 1) * 8].try_into().unwrap();
// s.push_str(hex::encode(b).as_str());
// }
// s
value.encode()
}
}
@@ -238,17 +241,6 @@ macro_rules! byte_array_type {
impl TryFrom<&str> for $name {
type Error = VeilidAPIError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
// let mut out = $name::default();
// if value == "" {
// return Ok(out);
// }
// if value.len() != ($size * 2) {
// apibail_generic!(concat!(stringify!($name), " is incorrect length"));
// }
// match hex::decode_to_slice(value, &mut out.bytes) {
// Ok(_) => Ok(out),
// Err(err) => Err(VeilidAPIError::generic(err)),
// }
Self::try_decode(value)
}
}
@@ -257,10 +249,18 @@ macro_rules! byte_array_type {
/////////////////////////////////////////
byte_array_type!(PublicKey, PUBLIC_KEY_LENGTH);
byte_array_type!(SecretKey, SECRET_KEY_LENGTH);
byte_array_type!(Signature, SIGNATURE_LENGTH);
byte_array_type!(PublicKeyDistance, PUBLIC_KEY_LENGTH);
byte_array_type!(Nonce, NONCE_LENGTH);
byte_array_type!(SharedSecret, SHARED_SECRET_LENGTH);
byte_array_type!(RouteId, ROUTE_ID_LENGTH);
byte_array_type!(PublicKey, PUBLIC_KEY_LENGTH, PUBLIC_KEY_LENGTH_ENCODED);
byte_array_type!(SecretKey, SECRET_KEY_LENGTH, SECRET_KEY_LENGTH_ENCODED);
byte_array_type!(Signature, SIGNATURE_LENGTH, SIGNATURE_LENGTH_ENCODED);
byte_array_type!(
PublicKeyDistance,
PUBLIC_KEY_LENGTH,
PUBLIC_KEY_LENGTH_ENCODED
);
byte_array_type!(Nonce, NONCE_LENGTH, NONCE_LENGTH_ENCODED);
byte_array_type!(
SharedSecret,
SHARED_SECRET_LENGTH,
SHARED_SECRET_LENGTH_ENCODED
);
byte_array_type!(RouteId, ROUTE_ID_LENGTH, ROUTE_ID_LENGTH_ENCODED);
+2 -2
View File
@@ -229,7 +229,7 @@ impl Crypto {
for nid in node_ids {
if nid.kind == sig.kind {
if let Some(vcrypto) = self.get(sig.kind) {
vcrypto.verify(&nid.key, data, &sig.signature)?;
vcrypto.verify(&nid.value, data, &sig.value)?;
out.push(nid.kind);
}
}
@@ -253,7 +253,7 @@ impl Crypto {
let mut out = Vec::<R>::with_capacity(typed_key_pairs.len());
for kp in typed_key_pairs {
if let Some(vcrypto) = self.get(kp.kind) {
let sig = vcrypto.sign(&kp.key, &kp.secret, data)?;
let sig = vcrypto.sign(&kp.value.key, &kp.value.secret, data)?;
out.push(transform(kp, sig))
}
}
-548
View File
@@ -1,548 +0,0 @@
use super::*;
use core::cmp::{Eq, Ord, PartialEq, PartialOrd};
use core::convert::TryInto;
use core::fmt;
use core::hash::Hash;
use rkyv::{Archive as RkyvArchive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
/// Cryptography version fourcc code
pub type CryptoKind = FourCC;
/// Sort best crypto kinds first
/// Better crypto kinds are 'less', ordered toward the front of a list
pub fn compare_crypto_kind(a: &CryptoKind, b: &CryptoKind) -> cmp::Ordering {
let a_idx = VALID_CRYPTO_KINDS.iter().position(|k| k == a);
let b_idx = VALID_CRYPTO_KINDS.iter().position(|k| k == b);
if let Some(a_idx) = a_idx {
if let Some(b_idx) = b_idx {
// Both are valid, prefer better crypto kind
a_idx.cmp(&b_idx)
} else {
// A is valid, B is not
cmp::Ordering::Less
}
} else if b_idx.is_some() {
// B is valid, A is not
cmp::Ordering::Greater
} else {
// Both are invalid, so use lex comparison
a.cmp(b)
}
}
/// Intersection of crypto kind vectors
pub fn common_crypto_kinds(a: &[CryptoKind], b: &[CryptoKind]) -> Vec<CryptoKind> {
let mut out = Vec::new();
for ack in a {
if b.contains(ack) {
out.push(*ack);
}
}
out
}
#[derive(
Clone,
Copy,
Debug,
Serialize,
Deserialize,
PartialOrd,
Ord,
PartialEq,
Eq,
Hash,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
pub struct KeyPair {
pub key: PublicKey,
pub secret: SecretKey,
}
impl KeyPair {
pub fn new(key: PublicKey, secret: SecretKey) -> Self {
Self { key, secret }
}
}
xxx make default template version here for secretkey
and put Vec<TypedKey<SecretKey>> in settings
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
pub struct TypedKey {
pub kind: CryptoKind,
pub key: PublicKey,
}
impl TypedKey {
pub fn new(kind: CryptoKind, key: PublicKey) -> Self {
Self { kind, key }
}
}
impl PartialOrd for TypedKey {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for TypedKey {
fn cmp(&self, other: &Self) -> cmp::Ordering {
let x = compare_crypto_kind(&self.kind, &other.kind);
if x != cmp::Ordering::Equal {
return x;
}
self.key.cmp(&other.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 })
}
}
impl<'de> Deserialize<'de> for TypedKey {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = <String as Deserialize>::deserialize(deserializer)?;
FromStr::from_str(&s).map_err(serde::de::Error::custom)
}
}
impl Serialize for TypedKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.collect_str(self)
}
}
#[derive(
Clone,
Debug,
Serialize,
Deserialize,
PartialOrd,
Ord,
PartialEq,
Eq,
Hash,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
#[serde(from = "Vec<TypedKey>", into = "Vec<TypedKey>")]
pub struct TypedKeySet {
items: Vec<TypedKey>,
}
impl TypedKeySet {
pub fn new() -> Self {
Self { items: Vec::new() }
}
pub fn with_capacity(cap: usize) -> Self {
Self {
items: Vec::with_capacity(cap),
}
}
pub fn kinds(&self) -> Vec<CryptoKind> {
let mut out = Vec::new();
for tk in &self.items {
out.push(tk.kind);
}
out.sort_by(compare_crypto_kind);
out
}
pub fn keys(&self) -> Vec<PublicKey> {
let mut out = Vec::new();
for tk in &self.items {
out.push(tk.key);
}
out
}
pub fn get(&self, kind: CryptoKind) -> Option<TypedKey> {
self.items.iter().find(|x| x.kind == kind).copied()
}
pub fn add(&mut self, typed_key: TypedKey) {
for x in &mut self.items {
if x.kind == typed_key.kind {
*x = typed_key;
return;
}
}
self.items.push(typed_key);
self.items.sort()
}
pub fn add_all(&mut self, typed_keys: &[TypedKey]) {
'outer: for typed_key in typed_keys {
for x in &mut self.items {
if x.kind == typed_key.kind {
*x = *typed_key;
continue 'outer;
}
}
self.items.push(*typed_key);
}
self.items.sort()
}
pub fn remove(&mut self, kind: CryptoKind) {
if let Some(idx) = self.items.iter().position(|x| x.kind == kind) {
self.items.remove(idx);
}
}
pub fn remove_all(&mut self, kinds: &[CryptoKind]) {
for k in kinds {
self.remove(*k);
}
}
/// Return preferred typed key of our supported crypto kinds
pub fn best(&self) -> Option<TypedKey> {
match self.items.first().copied() {
None => None,
Some(k) => {
if !VALID_CRYPTO_KINDS.contains(&k.kind) {
None
} else {
Some(k)
}
}
}
}
pub fn len(&self) -> usize {
self.items.len()
}
pub fn iter(&self) -> core::slice::Iter<'_, TypedKey> {
self.items.iter()
}
pub fn contains(&self, typed_key: &TypedKey) -> bool {
self.items.contains(typed_key)
}
pub fn contains_any(&self, typed_keys: &[TypedKey]) -> bool {
for typed_key in typed_keys {
if self.items.contains(typed_key) {
return true;
}
}
false
}
pub fn contains_key(&self, key: &PublicKey) -> bool {
for tk in &self.items {
if tk.key == *key {
return true;
}
}
false
}
}
impl core::ops::Deref for TypedKeySet {
type Target = [TypedKey];
#[inline]
fn deref(&self) -> &[TypedKey] {
&self.items
}
}
impl fmt::Display for TypedKeySet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "[")?;
let mut first = true;
for x in &self.items {
if !first {
write!(f, ",")?;
first = false;
}
write!(f, "{}", x)?;
}
write!(f, "]")
}
}
impl FromStr for TypedKeySet {
type Err = VeilidAPIError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut items = Vec::new();
if s.len() < 2 {
apibail_parse_error!("invalid length", s);
}
if &s[0..1] != "[" || &s[(s.len() - 1)..] != "]" {
apibail_parse_error!("invalid format", s);
}
for x in s[1..s.len() - 1].split(",") {
let tk = TypedKey::from_str(x.trim())?;
items.push(tk);
}
Ok(Self { items })
}
}
impl From<TypedKey> for TypedKeySet {
fn from(x: TypedKey) -> Self {
let mut tks = TypedKeySet::with_capacity(1);
tks.add(x);
tks
}
}
impl From<Vec<TypedKey>> for TypedKeySet {
fn from(x: Vec<TypedKey>) -> Self {
let mut tks = TypedKeySet::with_capacity(x.len());
tks.add_all(&x);
tks
}
}
impl Into<Vec<TypedKey>> for TypedKeySet {
fn into(self) -> Vec<TypedKey> {
self.items
}
}
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
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 PartialOrd for TypedKeyPair {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for TypedKeyPair {
fn cmp(&self, other: &Self) -> cmp::Ordering {
let x = compare_crypto_kind(&self.kind, &other.kind);
if x != cmp::Ordering::Equal {
return x;
}
let x = self.key.cmp(&other.key);
if x != cmp::Ordering::Equal {
return x;
}
self.secret.cmp(&other.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,
PartialEq,
Eq,
Hash,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
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 PartialOrd for TypedSignature {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for TypedSignature {
fn cmp(&self, other: &Self) -> cmp::Ordering {
let x = compare_crypto_kind(&self.kind, &other.kind);
if x != cmp::Ordering::Equal {
return x;
}
self.signature.cmp(&other.signature)
}
}
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,
PartialEq,
Eq,
Hash,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
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 PartialOrd for TypedKeySignature {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for TypedKeySignature {
fn cmp(&self, other: &Self) -> cmp::Ordering {
let x = compare_crypto_kind(&self.kind, &other.kind);
if x != cmp::Ordering::Equal {
return x;
}
let x = self.key.cmp(&other.key);
if x != cmp::Ordering::Equal {
return x;
}
self.signature.cmp(&other.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,
})
}
}
@@ -0,0 +1,184 @@
use super::*;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
pub struct CryptoTyped<K>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ Ord
+ PartialOrd
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
pub kind: CryptoKind,
pub value: K,
}
impl<K> CryptoTyped<K>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ Ord
+ PartialOrd
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
pub fn new(kind: CryptoKind, value: K) -> Self {
Self { kind, value }
}
}
impl<K> PartialOrd for CryptoTyped<K>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ Ord
+ PartialOrd
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<K> Ord for CryptoTyped<K>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ Ord
+ PartialOrd
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
fn cmp(&self, other: &Self) -> cmp::Ordering {
let x = compare_crypto_kind(&self.kind, &other.kind);
if x != cmp::Ordering::Equal {
return x;
}
self.value.cmp(&other.value)
}
}
impl<K> fmt::Display for CryptoTyped<K>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ Ord
+ PartialOrd
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{}:{}", self.kind, self.value)
}
}
impl<K> FromStr for CryptoTyped<K>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ Ord
+ PartialOrd
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
type Err = VeilidAPIError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let b = s.as_bytes();
if b.len() != (5 + K::encoded_len()) || 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 value = K::try_decode_bytes(&b[5..])?;
Ok(Self { kind, value })
}
}
impl<'de, K> Deserialize<'de> for CryptoTyped<K>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ Ord
+ PartialOrd
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = <String as Deserialize>::deserialize(deserializer)?;
FromStr::from_str(&s).map_err(serde::de::Error::custom)
}
}
impl<K> Serialize for CryptoTyped<K>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ Ord
+ PartialOrd
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.collect_str(self)
}
}
@@ -0,0 +1,303 @@
use super::*;
#[derive(
Clone,
Debug,
Serialize,
Deserialize,
PartialOrd,
Ord,
PartialEq,
Eq,
Hash,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
Default,
)]
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
#[serde(from = "Vec<CryptoTyped<K>>", into = "Vec<CryptoTyped<K>>")]
pub struct CryptoTypedSet<K = PublicKey>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
<Vec<CryptoTyped<K>> as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
items: Vec<CryptoTyped<K>>,
}
impl<K> CryptoTypedSet<K>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
pub fn new() -> Self {
Self { items: Vec::new() }
}
pub fn with_capacity(cap: usize) -> Self {
Self {
items: Vec::with_capacity(cap),
}
}
pub fn kinds(&self) -> Vec<CryptoKind> {
let mut out = Vec::new();
for tk in &self.items {
out.push(tk.kind);
}
out.sort_by(compare_crypto_kind);
out
}
pub fn keys(&self) -> Vec<K> {
let mut out = Vec::new();
for tk in &self.items {
out.push(tk.value);
}
out
}
pub fn get(&self, kind: CryptoKind) -> Option<CryptoTyped<K>> {
self.items.iter().find(|x| x.kind == kind).copied()
}
pub fn add(&mut self, typed_key: CryptoTyped<K>) {
for x in &mut self.items {
if x.kind == typed_key.kind {
*x = typed_key;
return;
}
}
self.items.push(typed_key);
self.items.sort()
}
pub fn add_all(&mut self, typed_keys: &[CryptoTyped<K>]) {
'outer: for typed_key in typed_keys {
for x in &mut self.items {
if x.kind == typed_key.kind {
*x = *typed_key;
continue 'outer;
}
}
self.items.push(*typed_key);
}
self.items.sort()
}
pub fn remove(&mut self, kind: CryptoKind) {
if let Some(idx) = self.items.iter().position(|x| x.kind == kind) {
self.items.remove(idx);
}
}
pub fn remove_all(&mut self, kinds: &[CryptoKind]) {
for k in kinds {
self.remove(*k);
}
}
/// Return preferred typed key of our supported crypto kinds
pub fn best(&self) -> Option<CryptoTyped<K>> {
match self.items.first().copied() {
None => None,
Some(k) => {
if !VALID_CRYPTO_KINDS.contains(&k.kind) {
None
} else {
Some(k)
}
}
}
}
pub fn len(&self) -> usize {
self.items.len()
}
pub fn iter(&self) -> core::slice::Iter<'_, CryptoTyped<K>> {
self.items.iter()
}
pub fn contains(&self, typed_key: &CryptoTyped<K>) -> bool {
self.items.contains(typed_key)
}
pub fn contains_any(&self, typed_keys: &[CryptoTyped<K>]) -> bool {
for typed_key in typed_keys {
if self.items.contains(typed_key) {
return true;
}
}
false
}
pub fn contains_key(&self, key: &K) -> bool {
for tk in &self.items {
if tk.value == *key {
return true;
}
}
false
}
}
impl<K> core::ops::Deref for CryptoTypedSet<K>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
type Target = [CryptoTyped<K>];
#[inline]
fn deref(&self) -> &[CryptoTyped<K>] {
&self.items
}
}
impl<K> fmt::Display for CryptoTypedSet<K>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "[")?;
let mut first = true;
for x in &self.items {
if !first {
write!(f, ",")?;
first = false;
}
write!(f, "{}", x)?;
}
write!(f, "]")
}
}
impl<K> FromStr for CryptoTypedSet<K>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
type Err = VeilidAPIError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut items = Vec::new();
if s.len() < 2 {
apibail_parse_error!("invalid length", s);
}
if &s[0..1] != "[" || &s[(s.len() - 1)..] != "]" {
apibail_parse_error!("invalid format", s);
}
for x in s[1..s.len() - 1].split(",") {
let tk = CryptoTyped::<K>::from_str(x.trim())?;
items.push(tk);
}
Ok(Self { items })
}
}
impl<K> From<CryptoTyped<K>> for CryptoTypedSet<K>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
fn from(x: CryptoTyped<K>) -> Self {
let mut tks = CryptoTypedSet::<K>::with_capacity(1);
tks.add(x);
tks
}
}
impl<K> From<Vec<CryptoTyped<K>>> for CryptoTypedSet<K>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
fn from(x: Vec<CryptoTyped<K>>) -> Self {
let mut tks = CryptoTypedSet::<K>::with_capacity(x.len());
tks.add_all(&x);
tks
}
}
impl<K> Into<Vec<CryptoTyped<K>>> for CryptoTypedSet<K>
where
K: Clone
+ Copy
+ fmt::Debug
+ fmt::Display
+ FromStr
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ Hash
+ RkyvArchive
+ Encodable,
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
{
fn into(self) -> Vec<CryptoTyped<K>> {
self.items
}
}
+85
View File
@@ -0,0 +1,85 @@
use super::*;
#[derive(
Clone,
Copy,
Serialize,
Deserialize,
PartialOrd,
Ord,
PartialEq,
Eq,
Hash,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
pub struct KeyPair {
pub key: PublicKey,
pub secret: SecretKey,
}
impl KeyPair {
pub fn new(key: PublicKey, secret: SecretKey) -> Self {
Self { key, secret }
}
}
impl Encodable for KeyPair {
fn encode(&self) -> String {
format!("{}:{}", self.key.encode(), self.secret.encode())
}
fn encoded_len() -> usize {
PublicKey::encoded_len() + 1 + SecretKey::encoded_len()
}
fn try_decode_bytes(b: &[u8]) -> Result<Self, VeilidAPIError> {
if b.len() != Self::encoded_len() {
apibail_parse_error!("input has wrong encoded length", format!("len={}", b.len()));
}
let key = PublicKey::try_decode_bytes(&b[0..PublicKey::encoded_len()])?;
let secret = SecretKey::try_decode_bytes(&b[(PublicKey::encoded_len() + 1)..])?;
Ok(KeyPair { key, secret })
}
}
impl fmt::Display for KeyPair {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.encode())
}
}
impl fmt::Debug for KeyPair {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, concat!(stringify!($name), "("))?;
write!(f, "{}", self.encode())?;
write!(f, ")")
}
}
impl From<&KeyPair> for String {
fn from(value: &KeyPair) -> Self {
value.encode()
}
}
impl FromStr for KeyPair {
type Err = VeilidAPIError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
KeyPair::try_from(s)
}
}
impl TryFrom<String> for KeyPair {
type Error = VeilidAPIError;
fn try_from(value: String) -> Result<Self, Self::Error> {
KeyPair::try_from(value.as_str())
}
}
impl TryFrom<&str> for KeyPair {
type Error = VeilidAPIError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
Self::try_decode(value)
}
}
+59
View File
@@ -0,0 +1,59 @@
use super::*;
use core::cmp::{Eq, Ord, PartialEq, PartialOrd};
use core::convert::TryInto;
use core::fmt;
use core::hash::Hash;
use rkyv::{Archive as RkyvArchive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
/// Cryptography version fourcc code
pub type CryptoKind = FourCC;
/// Sort best crypto kinds first
/// Better crypto kinds are 'less', ordered toward the front of a list
pub fn compare_crypto_kind(a: &CryptoKind, b: &CryptoKind) -> cmp::Ordering {
let a_idx = VALID_CRYPTO_KINDS.iter().position(|k| k == a);
let b_idx = VALID_CRYPTO_KINDS.iter().position(|k| k == b);
if let Some(a_idx) = a_idx {
if let Some(b_idx) = b_idx {
// Both are valid, prefer better crypto kind
a_idx.cmp(&b_idx)
} else {
// A is valid, B is not
cmp::Ordering::Less
}
} else if b_idx.is_some() {
// B is valid, A is not
cmp::Ordering::Greater
} else {
// Both are invalid, so use lex comparison
a.cmp(b)
}
}
/// Intersection of crypto kind vectors
pub fn common_crypto_kinds(a: &[CryptoKind], b: &[CryptoKind]) -> Vec<CryptoKind> {
let mut out = Vec::new();
for ack in a {
if b.contains(ack) {
out.push(*ack);
}
}
out
}
mod crypto_typed;
mod crypto_typed_set;
mod keypair;
pub use crypto_typed::*;
pub use crypto_typed_set::*;
pub use keypair::*;
pub type TypedKey = CryptoTyped<PublicKey>;
pub type TypedSecret = CryptoTyped<SecretKey>;
pub type TypedKeyPair = CryptoTyped<KeyPair>;
pub type TypedSignature = CryptoTyped<Signature>;
pub type TypedKeySet = CryptoTypedSet<PublicKey>;
pub type TypedSecretSet = CryptoTypedSet<SecretKey>;
+11 -7
View File
@@ -32,7 +32,16 @@ fn ed25519_to_x25519_sk(key: &ed::SecretKey) -> Result<xd::StaticSecret, VeilidA
Ok(xd::StaticSecret::from(lowbytes))
}
/// V1 CryptoSystem
pub fn vld0_generate_keypair() -> (PublicKey, SecretKey) {
let mut csprng = VeilidRng {};
let keypair = ed::Keypair::generate(&mut csprng);
let dht_key = PublicKey::new(keypair.public.to_bytes());
let dht_key_secret = SecretKey::new(keypair.secret.to_bytes());
(dht_key, dht_key_secret)
}
/// V0 CryptoSystem
#[derive(Clone)]
pub struct CryptoSystemVLD0 {
crypto: Crypto,
@@ -87,12 +96,7 @@ impl CryptoSystem for CryptoSystemVLD0 {
Ok(SharedSecret::new(sk_xd.diffie_hellman(&pk_xd).to_bytes()))
}
fn generate_keypair(&self) -> (PublicKey, SecretKey) {
let mut csprng = VeilidRng {};
let keypair = ed::Keypair::generate(&mut csprng);
let dht_key = PublicKey::new(keypair.public.to_bytes());
let dht_key_secret = SecretKey::new(keypair.secret.to_bytes());
(dht_key, dht_key_secret)
vld0_generate_keypair()
}
fn generate_hash(&self, data: &[u8]) -> PublicKey {
PublicKey::new(*blake3::hash(data).as_bytes())
+1
View File
@@ -35,6 +35,7 @@ mod veilid_layer_filter;
pub use self::api_tracing_layer::ApiTracingLayer;
pub use self::core_context::{api_startup, api_startup_json, UpdateCallback};
pub use self::crypto::vld0_generate_keypair;
pub use self::veilid_api::*;
pub use self::veilid_config::*;
pub use self::veilid_layer_filter::*;
+4 -4
View File
@@ -529,7 +529,7 @@ impl NetworkManager {
let node_id = routing_table.node_id(vcrypto.kind());
let node_id_secret = routing_table.node_id_secret(vcrypto.kind());
let receipt = Receipt::try_new(best_envelope_version(), node_id.kind, nonce, node_id.key, extra_data)?;
let receipt = Receipt::try_new(best_envelope_version(), node_id.kind, nonce, node_id.value, extra_data)?;
let out = receipt
.to_signed_data(self.crypto(), &node_id_secret)
.wrap_err("failed to generate signed receipt")?;
@@ -558,7 +558,7 @@ impl NetworkManager {
let node_id = routing_table.node_id(vcrypto.kind());
let node_id_secret = routing_table.node_id_secret(vcrypto.kind());
let receipt = Receipt::try_new(best_envelope_version(), node_id.kind, nonce, node_id.key, extra_data)?;
let receipt = Receipt::try_new(best_envelope_version(), node_id.kind, nonce, node_id.value, extra_data)?;
let out = receipt
.to_signed_data(self.crypto(), &node_id_secret)
.wrap_err("failed to generate signed receipt")?;
@@ -761,7 +761,7 @@ impl NetworkManager {
let nonce = vcrypto.random_nonce();
// Encode envelope
let envelope = Envelope::new(version, node_id.kind, ts, nonce, node_id.key, dest_node_id.key);
let envelope = Envelope::new(version, node_id.kind, ts, nonce, node_id.value, dest_node_id.value);
envelope
.to_encrypted_data(self.crypto(), body.as_ref(), &node_id_secret)
.wrap_err("envelope failed to encode")
@@ -1389,7 +1389,7 @@ impl NetworkManager {
let some_relay_nr = if self.check_client_whitelist(sender_id) {
// Full relay allowed, do a full resolve_node
match rpc.resolve_node(recipient_id.key).await {
match rpc.resolve_node(recipient_id.value).await {
Ok(v) => v,
Err(e) => {
log_net!(debug "failed to resolve recipient node for relay, dropping outbound relayed packet: {}" ,e);
+3 -3
View File
@@ -127,7 +127,7 @@ impl RoutingTableUnlockedInner {
pub fn node_id_typed_key_pairs(&self) -> Vec<TypedKeyPair> {
let mut tkps = Vec::new();
for (ck, v) in &self.node_id_keypairs {
tkps.push(TypedKeyPair::new(*ck, v.key, v.secret));
tkps.push(TypedKeyPair::new(*ck, *v));
}
tkps
}
@@ -139,7 +139,7 @@ impl RoutingTableUnlockedInner {
pub fn matches_own_node_id(&self, node_ids: &[TypedKey]) -> bool {
for ni in node_ids {
if let Some(v) = self.node_id_keypairs.get(&ni.kind) {
if v.key == ni.key {
if v.key == ni.value {
return true;
}
}
@@ -163,7 +163,7 @@ impl RoutingTableUnlockedInner {
(
node_id.kind,
vcrypto
.distance(&node_id.key, &self_node_id)
.distance(&node_id.value, &self_node_id)
.first_nonzero_bit()
.unwrap(),
)
@@ -68,7 +68,7 @@ impl RouteSetSpecDetail {
tks
}
pub fn get_best_route_set_key(&self) -> Option<PublicKey> {
self.get_route_set_keys().best().map(|k| k.key)
self.get_route_set_keys().best().map(|k| k.value)
}
pub fn set_hop_node_refs(&mut self, node_refs: Vec<NodeRef>) {
self.hop_node_refs = node_refs;
@@ -128,7 +128,7 @@ impl RouteSetSpecDetail {
let hops = &self.hop_node_refs;
let mut cache: Vec<u8> = Vec::with_capacity(hops.len() * PUBLIC_KEY_LENGTH);
for hop in hops {
cache.extend_from_slice(&hop.best_node_id().key.bytes);
cache.extend_from_slice(&hop.best_node_id().value.bytes);
}
cache
}
@@ -358,7 +358,7 @@ impl RouteSpecStore {
fn route_permutation_to_hop_cache(rti: &RoutingTableInner, nodes: &[NodeRef], perm: &[usize]) -> Vec<u8> {
let mut cache: Vec<u8> = Vec::with_capacity(perm.len() * PUBLIC_KEY_LENGTH);
for n in perm {
cache.extend_from_slice(&nodes[*n].locked(rti).best_node_id().key.bytes)
cache.extend_from_slice(&nodes[*n].locked(rti).best_node_id().value.bytes)
}
cache
}
@@ -491,7 +491,7 @@ impl RouteSpecStore {
for crypto_kind in crypto_kinds.iter().copied() {
let vcrypto = self.unlocked_inner.routing_table.crypto().get(crypto_kind).unwrap();
let (public_key, secret_key) = vcrypto.generate_keypair();
let hops: Vec<PublicKey> = route_nodes.iter().map(|v| nodes[*v].node_ids().get(crypto_kind).unwrap().key).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 {
crypto_kind,
@@ -543,16 +543,16 @@ impl RouteSpecStore {
return None;
};
let Some(rsid) = inner.content.get_id_by_key(&public_key.key) else {
log_rpc!(debug "route id does not exist: {:?}", public_key.key);
let Some(rsid) = inner.content.get_id_by_key(&public_key.value) else {
log_rpc!(debug "route id does not exist: {:?}", public_key.value);
return None;
};
let Some(rssd) = inner.content.get_detail(&rsid) else {
log_rpc!(debug "route detail does not exist: {:?}", rsid);
return None;
};
let Some(rsd) = rssd.get_route_by_key(&public_key.key) else {
log_rpc!(debug "route set {:?} does not have key: {:?}", rsid, public_key.key);
let Some(rsd) = rssd.get_route_by_key(&public_key.value) else {
log_rpc!(debug "route set {:?} does not have key: {:?}", rsid, public_key.value);
return None;
};
@@ -694,7 +694,7 @@ impl RouteSpecStore {
}
/// Check if a route id is remote or not
fn is_route_id_remote(&self, id: &RouteId) -> bool {
pub fn is_route_id_remote(&self, id: &RouteId) -> bool {
let inner = &mut *self.inner.lock();
let cur_ts = get_aligned_timestamp();
inner.cache.peek_remote_private_route_mut(cur_ts, &id).is_some()
@@ -847,7 +847,7 @@ impl RouteSpecStore {
let Some(vcrypto) = crypto.get(crypto_kind) else {
bail!("crypto not supported for route");
};
let pr_pubkey = private_route.public_key.key;
let pr_pubkey = private_route.public_key.value;
let pr_hopcount = private_route.hop_count as usize;
let max_route_hop_count = self.unlocked_inner.max_route_hop_count;
@@ -1092,7 +1092,7 @@ impl RouteSpecStore {
if let Some(preferred_key) = preferred_rssd.get_route_set_keys().get(crypto_kind) {
// Only use the preferred route if it doesn't contain the avoid nodes
if !preferred_rssd.contains_nodes(avoid_nodes) {
return Ok(Some(preferred_key.key));
return Ok(Some(preferred_key.value));
}
}
}
@@ -1131,7 +1131,7 @@ impl RouteSpecStore {
sr_route_id
};
let sr_pubkey = inner.content.get_detail(&sr_route_id).unwrap().get_route_set_keys().get(crypto_kind).unwrap().key;
let sr_pubkey = inner.content.get_detail(&sr_route_id).unwrap().get_route_set_keys().get(crypto_kind).unwrap().value;
Ok(Some(sr_pubkey))
}
@@ -1178,7 +1178,7 @@ impl RouteSpecStore {
let Some(node_id) = routing_table.node_ids().get(rsd.crypto_kind) else {
bail!("missing node id for crypto kind");
};
RouteNode::NodeId(node_id.key)
RouteNode::NodeId(node_id.value)
} else {
let Some(pi) = rti.get_own_peer_info(RoutingDomain::PublicInternet) else {
bail!("can't make private routes until our node info is valid");
@@ -1319,7 +1319,7 @@ impl RouteSpecStore {
}
// ensure this isn't also an allocated route
if inner.content.get_id_by_key(&private_route.public_key.key).is_some() {
if inner.content.get_id_by_key(&private_route.public_key.value).is_some() {
bail!("should not import allocated route");
}
}
@@ -1570,7 +1570,7 @@ impl RouteSpecStore {
if best_kind.is_none() || compare_crypto_kind(&tk.kind, best_kind.as_ref().unwrap()) == cmp::Ordering::Less {
best_kind = Some(tk.kind);
}
idbytes.extend_from_slice(&tk.key.bytes);
idbytes.extend_from_slice(&tk.value.bytes);
}
let Some(best_kind) = best_kind else {
bail!("no compatible crypto kinds in route");
@@ -1591,7 +1591,7 @@ impl RouteSpecStore {
if best_kind.is_none() || compare_crypto_kind(&private_route.public_key.kind, best_kind.as_ref().unwrap()) == cmp::Ordering::Less {
best_kind = Some(private_route.public_key.kind);
}
idbytes.extend_from_slice(&private_route.public_key.key.bytes);
idbytes.extend_from_slice(&private_route.public_key.value.bytes);
}
let Some(best_kind) = best_kind else {
bail!("no compatible crypto kinds in route");
@@ -114,14 +114,18 @@ impl RouteSpecStoreCache {
/// calculate how many times a node with a particular node id set has been used anywhere in the path of our allocated routes
pub fn get_used_node_count(&self, node_ids: &TypedKeySet) -> usize {
node_ids.iter().fold(0usize, |acc, k| {
acc + self.used_nodes.get(&k.key).cloned().unwrap_or_default()
acc + self.used_nodes.get(&k.value).cloned().unwrap_or_default()
})
}
/// calculate how many times a node with a particular node id set has been used at the end of the path of our allocated routes
pub fn get_used_end_node_count(&self, node_ids: &TypedKeySet) -> usize {
node_ids.iter().fold(0usize, |acc, k| {
acc + self.used_end_nodes.get(&k.key).cloned().unwrap_or_default()
acc + self
.used_end_nodes
.get(&k.value)
.cloned()
.unwrap_or_default()
})
}
@@ -135,7 +139,7 @@ impl RouteSpecStoreCache {
// also store in id by key table
for private_route in rprinfo.get_private_routes() {
self.remote_private_routes_by_key
.insert(private_route.public_key.key, id.clone());
.insert(private_route.public_key.value, id.clone());
}
let mut dead = None;
@@ -149,9 +153,9 @@ impl RouteSpecStoreCache {
// Follow the same logic as 'remove_remote_private_route' here
for dead_private_route in dead_rpri.get_private_routes() {
self.remote_private_routes_by_key
.remove(&dead_private_route.public_key.key)
.remove(&dead_private_route.public_key.value)
.unwrap();
self.invalidate_compiled_route_cache(&dead_private_route.public_key.key);
self.invalidate_compiled_route_cache(&dead_private_route.public_key.value);
}
self.dead_remote_routes.push(dead_id);
}
@@ -261,9 +265,9 @@ impl RouteSpecStoreCache {
};
for private_route in rprinfo.get_private_routes() {
self.remote_private_routes_by_key
.remove(&private_route.public_key.key)
.remove(&private_route.public_key.value)
.unwrap();
self.invalidate_compiled_route_cache(&private_route.public_key.key);
self.invalidate_compiled_route_cache(&private_route.public_key.value);
}
self.dead_remote_routes.push(id);
true
@@ -272,7 +276,7 @@ impl RouteSpecStoreCache {
/// Stores a compiled 'safety + private' route so we don't have to compile it again later
pub fn add_to_compiled_route_cache(&mut self, pr_pubkey: PublicKey, safety_route: SafetyRoute) {
let key = CompiledRouteCacheKey {
sr_pubkey: safety_route.public_key.key,
sr_pubkey: safety_route.public_key.value,
pr_pubkey,
};
@@ -605,14 +605,14 @@ impl RoutingTableInner {
// Remove any old node id for this crypto kind
let bucket_index = self.unlocked_inner.calculate_bucket_index(&old_node_id);
let bucket = self.get_bucket_mut(bucket_index);
bucket.remove_entry(&old_node_id.key);
bucket.remove_entry(&old_node_id.value);
self.unlocked_inner.kick_queue.lock().insert(bucket_index);
}
// Bucket the entry appropriately
let bucket_index = self.unlocked_inner.calculate_bucket_index(node_id);
let bucket = self.get_bucket_mut(bucket_index);
bucket.add_existing_entry(node_id.key, entry.clone());
bucket.add_existing_entry(node_id.value, entry.clone());
// Kick bucket
self.unlocked_inner.kick_queue.lock().insert(bucket_index);
@@ -649,7 +649,7 @@ impl RoutingTableInner {
}
let bucket_index = self.unlocked_inner.calculate_bucket_index(node_id);
let bucket = self.get_bucket(bucket_index);
if let Some(entry) = bucket.entry(&node_id.key) {
if let Some(entry) = bucket.entry(&node_id.value) {
// Best entry is the first one in sorted order that exists from the node id list
// Everything else that matches will be overwritten in the bucket and the
// existing noderefs will eventually unref and drop the old unindexed bucketentry
@@ -680,7 +680,7 @@ impl RoutingTableInner {
let first_node_id = node_ids[0];
let bucket_entry = self.unlocked_inner.calculate_bucket_index(&first_node_id);
let bucket = self.get_bucket_mut(bucket_entry);
let new_entry = bucket.add_new_entry(first_node_id.key);
let new_entry = bucket.add_new_entry(first_node_id.value);
self.unlocked_inner.kick_queue.lock().insert(bucket_entry);
// Update the other bucket entries with the remaining node ids
@@ -723,7 +723,7 @@ impl RoutingTableInner {
let bucket_index = self.unlocked_inner.calculate_bucket_index(&node_id);
let bucket = self.get_bucket(bucket_index);
bucket
.entry(&node_id.key)
.entry(&node_id.value)
.map(|e| NodeRef::new(outer_self, e, None))
}
@@ -760,7 +760,7 @@ impl RoutingTableInner {
}
let bucket_entry = self.unlocked_inner.calculate_bucket_index(&node_id);
let bucket = self.get_bucket(bucket_entry);
bucket.entry(&node_id.key).map(f)
bucket.entry(&node_id.value).map(f)
}
/// Shortcut function to add a node to our routing table if it doesn't exist
@@ -1174,8 +1174,8 @@ impl RoutingTableInner {
// since multiple cryptosystems are in use, the distance for a key is the shortest
// distance to that key over all supported cryptosystems
let da = vcrypto.distance(&a_key.key, &node_id.key);
let db = vcrypto.distance(&b_key.key, &node_id.key);
let da = vcrypto.distance(&a_key.value, &node_id.value);
let db = vcrypto.distance(&b_key.value, &node_id.value);
da.cmp(&db)
};
@@ -15,5 +15,5 @@ pub fn decode_typed_key(typed_key: &veilid_capnp::typed_key::Reader) -> Result<T
pub fn encode_typed_key(typed_key: &TypedKey, builder: &mut veilid_capnp::typed_key::Builder) {
builder.set_kind(u32::from_be_bytes(typed_key.kind.0));
let mut key_builder = builder.reborrow().init_key();
encode_key256(&typed_key.key, &mut key_builder);
encode_key256(&typed_key.value, &mut key_builder);
}
@@ -20,5 +20,5 @@ pub fn encode_typed_signature(
) {
builder.set_kind(u32::from_be_bytes(typed_signature.kind.0));
let mut sig_builder = builder.reborrow().init_signature();
encode_signature512(&typed_signature.signature, &mut sig_builder);
encode_signature512(&typed_signature.value, &mut sig_builder);
}
+4 -4
View File
@@ -223,12 +223,12 @@ impl RPCProcessor {
// Determine if we can use optimized nodeinfo
let route_node = if rss
.has_remote_private_route_seen_our_node_info(&private_route.public_key.key)
.has_remote_private_route_seen_our_node_info(&private_route.public_key.value)
{
if !routing_table.has_valid_own_node_info(RoutingDomain::PublicInternet) {
return Ok(NetworkResult::no_connection_other("Own node info must be valid to use private route"));
}
RouteNode::NodeId(routing_table.node_id(crypto_kind).key)
RouteNode::NodeId(routing_table.node_id(crypto_kind).value)
} else {
let Some(own_peer_info) =
routing_table.get_own_peer_info(RoutingDomain::PublicInternet) else {
@@ -245,11 +245,11 @@ impl RPCProcessor {
// Sent to a private route via a safety route, respond to private route
// Check for loopback test
let opt_private_route_id = rss.get_route_id_for_key(&private_route.public_key.key);
let opt_private_route_id = rss.get_route_id_for_key(&private_route.public_key.value);
let pr_key = if opt_private_route_id.is_some() && safety_spec.preferred_route == opt_private_route_id
{
// Private route is also safety route during loopback test
private_route.public_key.key
private_route.public_key.value
} else {
// Get the private route to respond to that matches the safety route spec we sent the request with
let Some(pr_key) = rss
+3 -3
View File
@@ -505,7 +505,7 @@ impl RPCProcessor {
// Get useful private route properties
let pr_is_stub = remote_private_route.is_stub();
let pr_hop_count = remote_private_route.hop_count;
let pr_pubkey = remote_private_route.public_key.key;
let pr_pubkey = remote_private_route.public_key.value;
let crypto_kind = remote_private_route.crypto_kind();
let Some(vcrypto) = self.crypto.get(crypto_kind) else {
return Err(RPCError::internal("crypto not available for selected private route"));
@@ -524,7 +524,7 @@ impl RPCProcessor {
}
};
let sr_is_stub = compiled_route.safety_route.is_stub();
let sr_pubkey = compiled_route.safety_route.public_key.key;
let sr_pubkey = compiled_route.safety_route.public_key.value;
// Encrypt routed operation
// Xmsg + ENC(Xmsg, DH(PKapr, SKbsr))
@@ -599,7 +599,7 @@ impl RPCProcessor {
let reply_private_route = match operation.kind() {
RPCOperationKind::Question(q) => match q.respond_to() {
RespondTo::Sender => None,
RespondTo::PrivateRoute(pr) => Some(pr.public_key.key),
RespondTo::PrivateRoute(pr) => Some(pr.public_key.value),
},
RPCOperationKind::Statement(_) | RPCOperationKind::Answer(_) => None,
};
@@ -60,7 +60,7 @@ impl RPCProcessor {
let sender = msg
.opt_sender_nr
.as_ref()
.map(|nr| nr.node_ids().get(crypto_kind).unwrap().key);
.map(|nr| nr.node_ids().get(crypto_kind).unwrap().value);
// Register a waiter for this app call
let id = msg.operation.op_id();
@@ -37,7 +37,7 @@ impl RPCProcessor {
let sender = msg
.opt_sender_nr
.as_ref()
.map(|nr| nr.node_ids().get(crypto_kind).unwrap().key);
.map(|nr| nr.node_ids().get(crypto_kind).unwrap().value);
// Pass the message up through the update callback
let message = app_message.message;
+9 -9
View File
@@ -111,7 +111,7 @@ impl RPCProcessor {
// 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 dh_secret = vcrypto
.cached_dh(&remote_sr_pubkey.key, &node_id_secret)
.cached_dh(&remote_sr_pubkey.value, &node_id_secret)
.map_err(RPCError::protocol)?;
let body = match vcrypto.decrypt_aead(
&routed_operation.data,
@@ -131,7 +131,7 @@ impl RPCProcessor {
// Pass message to RPC system
self.enqueue_safety_routed_message(
detail,
remote_sr_pubkey.key,
remote_sr_pubkey.value,
routed_operation.sequencing,
body,
)
@@ -166,7 +166,7 @@ impl RPCProcessor {
(
rsd.secret_key,
SafetySpec {
preferred_route: rss.get_route_id_for_key(&pr_pubkey.key),
preferred_route: rss.get_route_id_for_key(&pr_pubkey.value),
hop_count: rssd.hop_count(),
stability: rssd.get_stability(),
sequencing: routed_operation.sequencing,
@@ -181,7 +181,7 @@ impl RPCProcessor {
// 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 private routes?
let dh_secret = vcrypto
.cached_dh(&remote_sr_pubkey.key, &secret_key)
.cached_dh(&remote_sr_pubkey.value, &secret_key)
.map_err(RPCError::protocol)?;
let body = vcrypto
.decrypt_aead(
@@ -197,8 +197,8 @@ impl RPCProcessor {
// Pass message to RPC system
self.enqueue_private_routed_message(
detail,
remote_sr_pubkey.key,
pr_pubkey.key,
remote_sr_pubkey.value,
pr_pubkey.value,
safety_spec,
body,
)
@@ -315,7 +315,7 @@ impl RPCProcessor {
// 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 dh_secret = vcrypto
.cached_dh(&pr_pubkey.key, &node_id_secret)
.cached_dh(&pr_pubkey.value, &node_id_secret)
.map_err(RPCError::protocol)?;
let dec_blob_data = match vcrypto.decrypt_aead(
&route_hop_data.blob,
@@ -347,7 +347,7 @@ impl RPCProcessor {
let node_id = self.routing_table.node_id(crypto_kind);
let node_id_secret = self.routing_table.node_id_secret(crypto_kind);
let sig = vcrypto
.sign(&node_id.key, &node_id_secret, &route_operation.data)
.sign(&node_id.value, &node_id_secret, &route_operation.data)
.map_err(RPCError::internal)?;
route_operation.signatures.push(sig);
}
@@ -394,7 +394,7 @@ impl RPCProcessor {
// 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 dh_secret = vcrypto
.cached_dh(&route.safety_route.public_key.key, &node_id_secret)
.cached_dh(&route.safety_route.public_key.value, &node_id_secret)
.map_err(RPCError::protocol)?;
let mut dec_blob_data = vcrypto
.decrypt_aead(
@@ -71,7 +71,7 @@ pub async fn test_signed_node_info() {
let sni = SignedDirectNodeInfo::make_signatures(
crypto.clone(),
vec![TypedKeyPair::new(ck, pkey, skey)],
vec![TypedKeyPair::new(ck, KeyPair::new(pkey, skey))],
node_info.clone(),
)
.unwrap();
@@ -107,7 +107,7 @@ pub async fn test_signed_node_info() {
let sni2 = SignedRelayedNodeInfo::make_signatures(
crypto.clone(),
vec![TypedKeyPair::new(ck, pkey2, skey2)],
vec![TypedKeyPair::new(ck, KeyPair::new(pkey2, skey2))],
node_info2.clone(),
tks.clone(),
sni.clone(),
+8 -10
View File
@@ -1902,11 +1902,10 @@ impl SignedDirectNodeInfo {
) -> Result<Self, VeilidAPIError> {
let timestamp = get_aligned_timestamp();
let node_info_bytes = Self::make_signature_bytes(&node_info, timestamp)?;
let typed_signatures = crypto.generate_signatures(
&node_info_bytes,
&typed_key_pairs,
TypedSignature::from_pair_sig,
)?;
let typed_signatures =
crypto.generate_signatures(&node_info_bytes, &typed_key_pairs, |kp, s| {
TypedSignature::new(kp.kind, s)
})?;
Ok(Self {
node_info,
timestamp,
@@ -1997,11 +1996,10 @@ impl SignedRelayedNodeInfo {
let timestamp = get_aligned_timestamp();
let node_info_bytes =
Self::make_signature_bytes(&node_info, &relay_ids, &relay_info, timestamp)?;
let typed_signatures = crypto.generate_signatures(
&node_info_bytes,
&typed_key_pairs,
TypedSignature::from_pair_sig,
)?;
let typed_signatures =
crypto.generate_signatures(&node_info_bytes, &typed_key_pairs, |kp, s| {
TypedSignature::new(kp.kind, s)
})?;
Ok(Self {
node_info,
relay_ids,
+63 -35
View File
@@ -613,38 +613,70 @@ impl VeilidConfig {
cb: ConfigCallback,
update_cb: UpdateCallback,
) -> Result<(), VeilidAPIError> {
macro_rules! get_config {
($key:expr) => {
let keyname = &stringify!($key)[6..];
let v = cb(keyname.to_owned())?;
$key = match v.downcast() {
Ok(v) => *v,
Err(_) => {
apibail_generic!(format!("incorrect type for key {}", keyname))
}
};
};
}
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.with_mut(|inner| {
// Simple config transformation
macro_rules! get_config {
($key:expr) => {
let keyname = &stringify!($key)[6..];
let v = cb(keyname.to_owned())?;
$key = match v.downcast() {
Ok(v) => *v,
Err(_) => {
apibail_generic!(format!("incorrect type for key {}", keyname))
}
};
};
}
// 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: Option<TypedKeySet> = match keys.downcast() {
Ok(v) => *v,
Err(_) => {
apibail_generic!(
"incorrect type for key 'network.routing_table.node_id'".to_owned()
)
}
};
let keys = keys.unwrap_or_default();
let secrets = cb("network.routing_table.node_id_secret".to_owned())?;
let secrets: Option<TypedSecretSet> = match secrets.downcast() {
Ok(v) => *v,
Err(_) => {
apibail_generic!(
"incorrect type for key 'network.routing_table.node_id_secret'"
.to_owned()
)
}
};
let secrets = secrets.unwrap_or_default();
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);
}
}
};
}
get_config!(inner.program_name);
get_config!(inner.namespace);
get_config!(inner.capabilities.protocol_udp);
@@ -670,11 +702,7 @@ impl VeilidConfig {
get_config!(inner.network.max_connection_frequency_per_min);
get_config!(inner.network.client_whitelist_timeout_ms);
get_config!(inner.network.reverse_connection_receipt_time_ms);
get_config!(inner.network.hole_punch_receipt_time_ms);
for ck in VALID_CRYPTO_KINDS {
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_node_ids!();
get_config!(inner.network.routing_table.bootstrap);
get_config!(inner.network.routing_table.limit_over_attached);
get_config!(inner.network.routing_table.limit_fully_attached);