try multiple cryptosystems
This commit is contained in:
		| @@ -10,7 +10,7 @@ license = "LGPL-2.0-or-later OR MPL-2.0 OR (MIT AND BSD-3-Clause)" | |||||||
| crate-type = ["cdylib", "staticlib", "rlib"] | crate-type = ["cdylib", "staticlib", "rlib"] | ||||||
|  |  | ||||||
| [features] | [features] | ||||||
| default = [ "enable-crypto-vld0" ] | default = [ "enable-crypto-none", "enable-crypto-vld0" ] | ||||||
| enable-crypto-vld0 = [] | enable-crypto-vld0 = [] | ||||||
| enable-crypto-none = [] | enable-crypto-none = [] | ||||||
| rt-async-std = ["async-std", "async-std-resolver", "async_executors/async_std", "rtnetlink?/smol_socket", "veilid-tools/rt-async-std"] | rt-async-std = ["async-std", "async-std-resolver", "async_executors/async_std", "rtnetlink?/smol_socket", "veilid-tools/rt-async-std"] | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | mod blake3digest512; | ||||||
| mod byte_array_types; | mod byte_array_types; | ||||||
| mod dh_cache; | mod dh_cache; | ||||||
| mod envelope; | mod envelope; | ||||||
| @@ -6,9 +7,13 @@ mod types; | |||||||
| mod value; | mod value; | ||||||
|  |  | ||||||
| pub mod crypto_system; | pub mod crypto_system; | ||||||
|  | #[cfg(feature = "enable-crypto-none")] | ||||||
|  | pub mod none; | ||||||
| pub mod tests; | pub mod tests; | ||||||
|  | #[cfg(feature = "enable-crypto-vld0")] | ||||||
| pub mod vld0; | pub mod vld0; | ||||||
|  |  | ||||||
|  | pub use blake3digest512::*; | ||||||
| pub use byte_array_types::*; | pub use byte_array_types::*; | ||||||
| pub use crypto_system::*; | pub use crypto_system::*; | ||||||
| pub use dh_cache::*; | pub use dh_cache::*; | ||||||
| @@ -16,6 +21,10 @@ pub use envelope::*; | |||||||
| pub use receipt::*; | pub use receipt::*; | ||||||
| pub use types::*; | pub use types::*; | ||||||
| pub use value::*; | pub use value::*; | ||||||
|  |  | ||||||
|  | #[cfg(feature = "enable-crypto-none")] | ||||||
|  | pub use none::*; | ||||||
|  | #[cfg(feature = "enable-crypto-vld0")] | ||||||
| pub use vld0::*; | pub use vld0::*; | ||||||
|  |  | ||||||
| use crate::*; | use crate::*; | ||||||
| @@ -24,11 +33,26 @@ use hashlink::linked_hash_map::Entry; | |||||||
| use hashlink::LruCache; | use hashlink::LruCache; | ||||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||||
|  |  | ||||||
| // Handle to a particular cryptosystem | /// Handle to a particular cryptosystem | ||||||
| pub type CryptoSystemVersion = Arc<dyn CryptoSystem + Send + Sync>; | pub type CryptoSystemVersion = Arc<dyn CryptoSystem + Send + Sync>; | ||||||
|  |  | ||||||
| /// Crypto kinds in order of preference, best cryptosystem is the first one, worst is the last one | cfg_if! { | ||||||
| pub const VALID_CRYPTO_KINDS: [CryptoKind; 1] = [CRYPTO_KIND_VLD0]; |     if #[cfg(all(feature = "enable-crypto-none", feature = "enable-crypto-vld0"))] { | ||||||
|  |         /// Crypto kinds in order of preference, best cryptosystem is the first one, worst is the last one | ||||||
|  |         pub const VALID_CRYPTO_KINDS: [CryptoKind; 2] = [CRYPTO_KIND_VLD0, CRYPTO_KIND_NONE]; | ||||||
|  |     } | ||||||
|  |     else if #[cfg(feature = "enable-crypto-none")] { | ||||||
|  |         /// Crypto kinds in order of preference, best cryptosystem is the first one, worst is the last one | ||||||
|  |         pub const VALID_CRYPTO_KINDS: [CryptoKind; 1] = [CRYPTO_KIND_NONE]; | ||||||
|  |     } | ||||||
|  |     else if #[cfg(feature = "enable-crypto-vld0")] { | ||||||
|  |         /// Crypto kinds in order of preference, best cryptosystem is the first one, worst is the last one | ||||||
|  |         pub const VALID_CRYPTO_KINDS: [CryptoKind; 1] = [CRYPTO_KIND_VLD0]; | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         compile_error!("No crypto kinds enabled, specify an enable-crypto- feature"); | ||||||
|  |     } | ||||||
|  | } | ||||||
| /// Number of cryptosystem signatures to keep on structures if many are present beyond the ones we consider valid | /// Number of cryptosystem signatures to keep on structures if many are present beyond the ones we consider valid | ||||||
| pub const MAX_CRYPTO_KINDS: usize = 3; | pub const MAX_CRYPTO_KINDS: usize = 3; | ||||||
| /// Return the best cryptosystem kind we support | /// Return the best cryptosystem kind we support | ||||||
| @@ -36,7 +60,7 @@ pub fn best_crypto_kind() -> CryptoKind { | |||||||
|     VALID_CRYPTO_KINDS[0] |     VALID_CRYPTO_KINDS[0] | ||||||
| } | } | ||||||
|  |  | ||||||
| // Version number of envelope format | /// Version number of envelope format | ||||||
| pub type EnvelopeVersion = u8; | pub type EnvelopeVersion = u8; | ||||||
|  |  | ||||||
| /// Envelope versions in order of preference, best envelope version is the first one, worst is the last one | /// Envelope versions in order of preference, best envelope version is the first one, worst is the last one | ||||||
| @@ -51,7 +75,10 @@ pub fn best_envelope_version() -> EnvelopeVersion { | |||||||
| struct CryptoInner { | struct CryptoInner { | ||||||
|     dh_cache: DHCache, |     dh_cache: DHCache, | ||||||
|     flush_future: Option<SendPinBoxFuture<()>>, |     flush_future: Option<SendPinBoxFuture<()>>, | ||||||
|  |     #[cfg(feature = "enable-crypto-vld0")] | ||||||
|     crypto_vld0: Option<Arc<dyn CryptoSystem + Send + Sync>>, |     crypto_vld0: Option<Arc<dyn CryptoSystem + Send + Sync>>, | ||||||
|  |     #[cfg(feature = "enable-crypto-none")] | ||||||
|  |     crypto_none: Option<Arc<dyn CryptoSystem + Send + Sync>>, | ||||||
| } | } | ||||||
|  |  | ||||||
| struct CryptoUnlockedInner { | struct CryptoUnlockedInner { | ||||||
| @@ -72,7 +99,10 @@ impl Crypto { | |||||||
|         CryptoInner { |         CryptoInner { | ||||||
|             dh_cache: DHCache::new(DH_CACHE_SIZE), |             dh_cache: DHCache::new(DH_CACHE_SIZE), | ||||||
|             flush_future: None, |             flush_future: None, | ||||||
|  |             #[cfg(feature = "enable-crypto-vld0")] | ||||||
|             crypto_vld0: None, |             crypto_vld0: None, | ||||||
|  |             #[cfg(feature = "enable-crypto-none")] | ||||||
|  |             crypto_none: None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -90,7 +120,15 @@ impl Crypto { | |||||||
|             inner: Arc::new(Mutex::new(Self::new_inner())), |             inner: Arc::new(Mutex::new(Self::new_inner())), | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         out.inner.lock().crypto_vld0 = Some(Arc::new(vld0::CryptoSystemVLD0::new(out.clone()))); |         #[cfg(feature = "enable-crypto-vld0")] | ||||||
|  |         { | ||||||
|  |             out.inner.lock().crypto_vld0 = Some(Arc::new(vld0::CryptoSystemVLD0::new(out.clone()))); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         #[cfg(feature = "enable-crypto-none")] | ||||||
|  |         { | ||||||
|  |             out.inner.lock().crypto_none = Some(Arc::new(none::CryptoSystemNONE::new(out.clone()))); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         out |         out | ||||||
|     } |     } | ||||||
| @@ -203,7 +241,10 @@ impl Crypto { | |||||||
|     pub fn get(&self, kind: CryptoKind) -> Option<CryptoSystemVersion> { |     pub fn get(&self, kind: CryptoKind) -> Option<CryptoSystemVersion> { | ||||||
|         let inner = self.inner.lock(); |         let inner = self.inner.lock(); | ||||||
|         match kind { |         match kind { | ||||||
|  |             #[cfg(feature = "enable-crypto-vld0")] | ||||||
|             CRYPTO_KIND_VLD0 => Some(inner.crypto_vld0.clone().unwrap()), |             CRYPTO_KIND_VLD0 => Some(inner.crypto_vld0.clone().unwrap()), | ||||||
|  |             #[cfg(feature = "enable-crypto-none")] | ||||||
|  |             CRYPTO_KIND_NONE => Some(inner.crypto_none.clone().unwrap()), | ||||||
|             _ => None, |             _ => None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -262,10 +303,16 @@ impl Crypto { | |||||||
|     /// Generate keypair |     /// Generate keypair | ||||||
|     /// Does not require startup/init |     /// Does not require startup/init | ||||||
|     pub fn generate_keypair(crypto_kind: CryptoKind) -> Result<TypedKeyPair, VeilidAPIError> { |     pub fn generate_keypair(crypto_kind: CryptoKind) -> Result<TypedKeyPair, VeilidAPIError> { | ||||||
|  |         #[cfg(feature = "enable-crypto-vld0")] | ||||||
|         if crypto_kind == CRYPTO_KIND_VLD0 { |         if crypto_kind == CRYPTO_KIND_VLD0 { | ||||||
|             let kp = vld0_generate_keypair(); |             let kp = vld0_generate_keypair(); | ||||||
|             return Ok(TypedKeyPair::new(crypto_kind, kp)); |             return Ok(TypedKeyPair::new(crypto_kind, kp)); | ||||||
|         } |         } | ||||||
|  |         #[cfg(feature = "enable-crypto-none")] | ||||||
|  |         if crypto_kind == CRYPTO_KIND_NONE { | ||||||
|  |             let kp = none_generate_keypair(); | ||||||
|  |             return Ok(TypedKeyPair::new(crypto_kind, kp)); | ||||||
|  |         } | ||||||
|         Err(VeilidAPIError::generic("invalid crypto kind")) |         Err(VeilidAPIError::generic("invalid crypto kind")) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,62 +1,68 @@ | |||||||
| pub mod blake3digest512; |  | ||||||
| pub use blake3digest512::*; |  | ||||||
|  |  | ||||||
| use super::*; | use super::*; | ||||||
|  |  | ||||||
| use chacha20::cipher::{KeyIvInit, StreamCipher}; |  | ||||||
| use chacha20::XChaCha20; |  | ||||||
| use chacha20poly1305 as ch; |  | ||||||
| use chacha20poly1305::aead::{AeadInPlace, NewAead}; |  | ||||||
| use core::convert::TryInto; |  | ||||||
| use curve25519_dalek as cd; |  | ||||||
| use digest::Digest; | use digest::Digest; | ||||||
| use ed25519_dalek as ed; | use rand::RngCore; | ||||||
| use x25519_dalek as xd; |  | ||||||
|  |  | ||||||
| const AEAD_OVERHEAD: usize = 16; | const AEAD_OVERHEAD: usize = PUBLIC_KEY_LENGTH; | ||||||
| pub const CRYPTO_KIND_VLD0: CryptoKind = FourCC([b'V', b'L', b'D', b'0']); | pub const CRYPTO_KIND_NONE: CryptoKind = FourCC([b'N', b'O', b'N', b'E']); | ||||||
|  |  | ||||||
| fn ed25519_to_x25519_pk(key: &ed::PublicKey) -> Result<xd::PublicKey, VeilidAPIError> { | pub fn none_generate_keypair() -> KeyPair { | ||||||
|     let bytes = key.to_bytes(); |  | ||||||
|     let compressed = cd::edwards::CompressedEdwardsY(bytes); |  | ||||||
|     let point = compressed |  | ||||||
|         .decompress() |  | ||||||
|         .ok_or_else(|| VeilidAPIError::internal("ed25519_to_x25519_pk failed"))?; |  | ||||||
|     let mp = point.to_montgomery(); |  | ||||||
|     Ok(xd::PublicKey::from(mp.to_bytes())) |  | ||||||
| } |  | ||||||
| fn ed25519_to_x25519_sk(key: &ed::SecretKey) -> Result<xd::StaticSecret, VeilidAPIError> { |  | ||||||
|     let exp = ed::ExpandedSecretKey::from(key); |  | ||||||
|     let bytes: [u8; ed::EXPANDED_SECRET_KEY_LENGTH] = exp.to_bytes(); |  | ||||||
|     let lowbytes: [u8; 32] = bytes[0..32].try_into().map_err(VeilidAPIError::internal)?; |  | ||||||
|     Ok(xd::StaticSecret::from(lowbytes)) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| pub fn vld0_generate_keypair() -> KeyPair { |  | ||||||
|     let mut csprng = VeilidRng {}; |     let mut csprng = VeilidRng {}; | ||||||
|     let keypair = ed::Keypair::generate(&mut csprng); |     let mut pub_bytes = [0u8; PUBLIC_KEY_LENGTH]; | ||||||
|     let dht_key = PublicKey::new(keypair.public.to_bytes()); |     let mut sec_bytes = [0u8; SECRET_KEY_LENGTH]; | ||||||
|     let dht_key_secret = SecretKey::new(keypair.secret.to_bytes()); |     csprng.fill_bytes(&mut pub_bytes); | ||||||
|  |     for n in 0..PUBLIC_KEY_LENGTH { | ||||||
|  |         sec_bytes[n] = !pub_bytes[n]; | ||||||
|  |     } | ||||||
|  |     let dht_key = PublicKey::new(pub_bytes); | ||||||
|  |     let dht_key_secret = SecretKey::new(sec_bytes); | ||||||
|     KeyPair::new(dht_key, dht_key_secret) |     KeyPair::new(dht_key, dht_key_secret) | ||||||
| } | } | ||||||
|  |  | ||||||
| /// V0 CryptoSystem | fn do_xor_32(a: &[u8], b: &[u8]) -> [u8; 32] { | ||||||
|  |     let mut out = [0u8; 32]; | ||||||
|  |     for n in 0..32 { | ||||||
|  |         out[n] = a[n] ^ b[n]; | ||||||
|  |     } | ||||||
|  |     out | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn do_xor_inplace(a: &mut [u8], key: &[u8]) { | ||||||
|  |     for n in 0..a.len() { | ||||||
|  |         a[n] ^= key[n % key.len()]; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn do_xor_b2b(a: &[u8], b: &mut [u8], key: &[u8]) { | ||||||
|  |     for n in 0..a.len() { | ||||||
|  |         b[n] = a[n] ^ key[n % key.len()]; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn is_bytes_eq_32(a: &[u8], v: u8) -> bool { | ||||||
|  |     for n in 0..32 { | ||||||
|  |         if a[n] != v { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     true | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// None CryptoSystem | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| pub struct CryptoSystemVLD0 { | pub struct CryptoSystemNONE { | ||||||
|     crypto: Crypto, |     crypto: Crypto, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl CryptoSystemVLD0 { | impl CryptoSystemNONE { | ||||||
|     pub fn new(crypto: Crypto) -> Self { |     pub fn new(crypto: Crypto) -> Self { | ||||||
|         Self { crypto } |         Self { crypto } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl CryptoSystem for CryptoSystemVLD0 { | impl CryptoSystem for CryptoSystemNONE { | ||||||
|     // Accessors |     // Accessors | ||||||
|     fn kind(&self) -> CryptoKind { |     fn kind(&self) -> CryptoKind { | ||||||
|         CRYPTO_KIND_VLD0 |         CRYPTO_KIND_NONE | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn crypto(&self) -> Crypto { |     fn crypto(&self) -> Crypto { | ||||||
| @@ -70,17 +76,17 @@ impl CryptoSystem for CryptoSystemVLD0 { | |||||||
|         secret: &SecretKey, |         secret: &SecretKey, | ||||||
|     ) -> Result<SharedSecret, VeilidAPIError> { |     ) -> Result<SharedSecret, VeilidAPIError> { | ||||||
|         self.crypto |         self.crypto | ||||||
|             .cached_dh_internal::<CryptoSystemVLD0>(self, key, secret) |             .cached_dh_internal::<CryptoSystemNONE>(self, key, secret) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Generation |     // Generation | ||||||
|     fn random_nonce(&self) -> Nonce { |     fn random_nonce(&self) -> Nonce { | ||||||
|         let mut nonce = [0u8; 24]; |         let mut nonce = [0u8; NONCE_LENGTH]; | ||||||
|         random_bytes(&mut nonce).unwrap(); |         random_bytes(&mut nonce).unwrap(); | ||||||
|         Nonce::new(nonce) |         Nonce::new(nonce) | ||||||
|     } |     } | ||||||
|     fn random_shared_secret(&self) -> SharedSecret { |     fn random_shared_secret(&self) -> SharedSecret { | ||||||
|         let mut s = [0u8; 32]; |         let mut s = [0u8; SHARED_SECRET_LENGTH]; | ||||||
|         random_bytes(&mut s).unwrap(); |         random_bytes(&mut s).unwrap(); | ||||||
|         SharedSecret::new(s) |         SharedSecret::new(s) | ||||||
|     } |     } | ||||||
| @@ -89,14 +95,11 @@ impl CryptoSystem for CryptoSystemVLD0 { | |||||||
|         key: &PublicKey, |         key: &PublicKey, | ||||||
|         secret: &SecretKey, |         secret: &SecretKey, | ||||||
|     ) -> Result<SharedSecret, VeilidAPIError> { |     ) -> Result<SharedSecret, VeilidAPIError> { | ||||||
|         let pk_ed = ed::PublicKey::from_bytes(&key.bytes).map_err(VeilidAPIError::internal)?; |         let s = do_xor_32(&key.bytes, &secret.bytes); | ||||||
|         let pk_xd = ed25519_to_x25519_pk(&pk_ed)?; |         Ok(SharedSecret::new(s)) | ||||||
|         let sk_ed = ed::SecretKey::from_bytes(&secret.bytes).map_err(VeilidAPIError::internal)?; |  | ||||||
|         let sk_xd = ed25519_to_x25519_sk(&sk_ed)?; |  | ||||||
|         Ok(SharedSecret::new(sk_xd.diffie_hellman(&pk_xd).to_bytes())) |  | ||||||
|     } |     } | ||||||
|     fn generate_keypair(&self) -> KeyPair { |     fn generate_keypair(&self) -> KeyPair { | ||||||
|         vld0_generate_keypair() |         none_generate_keypair() | ||||||
|     } |     } | ||||||
|     fn generate_hash(&self, data: &[u8]) -> PublicKey { |     fn generate_hash(&self, data: &[u8]) -> PublicKey { | ||||||
|         PublicKey::new(*blake3::hash(data).as_bytes()) |         PublicKey::new(*blake3::hash(data).as_bytes()) | ||||||
| @@ -123,7 +126,6 @@ impl CryptoSystem for CryptoSystemVLD0 { | |||||||
|     } |     } | ||||||
|     fn validate_hash(&self, data: &[u8], dht_key: &PublicKey) -> bool { |     fn validate_hash(&self, data: &[u8], dht_key: &PublicKey) -> bool { | ||||||
|         let bytes = *blake3::hash(data).as_bytes(); |         let bytes = *blake3::hash(data).as_bytes(); | ||||||
|  |  | ||||||
|         bytes == dht_key.bytes |         bytes == dht_key.bytes | ||||||
|     } |     } | ||||||
|     fn validate_hash_reader( |     fn validate_hash_reader( | ||||||
| @@ -154,22 +156,21 @@ impl CryptoSystem for CryptoSystemVLD0 { | |||||||
|         dht_key_secret: &SecretKey, |         dht_key_secret: &SecretKey, | ||||||
|         data: &[u8], |         data: &[u8], | ||||||
|     ) -> Result<Signature, VeilidAPIError> { |     ) -> Result<Signature, VeilidAPIError> { | ||||||
|         let mut kpb: [u8; SECRET_KEY_LENGTH + PUBLIC_KEY_LENGTH] = |         if !is_bytes_eq_32(&do_xor_32(&dht_key.bytes, &dht_key_secret.bytes), 0xFFu8) { | ||||||
|             [0u8; SECRET_KEY_LENGTH + PUBLIC_KEY_LENGTH]; |             return Err(VeilidAPIError::parse_error( | ||||||
|  |                 "Keypair is invalid", | ||||||
|         kpb[..SECRET_KEY_LENGTH].copy_from_slice(&dht_key_secret.bytes); |                 "invalid keys", | ||||||
|         kpb[SECRET_KEY_LENGTH..].copy_from_slice(&dht_key.bytes); |             )); | ||||||
|         let keypair = ed::Keypair::from_bytes(&kpb) |         } | ||||||
|             .map_err(|e| VeilidAPIError::parse_error("Keypair is invalid", e))?; |  | ||||||
|  |  | ||||||
|         let mut dig = Blake3Digest512::new(); |         let mut dig = Blake3Digest512::new(); | ||||||
|         dig.update(data); |         dig.update(data); | ||||||
|  |         let sig = dig.finalize(); | ||||||
|         let sig = keypair |         let in_sig_bytes: [u8; SIGNATURE_LENGTH] = sig.into(); | ||||||
|             .sign_prehashed(dig, None) |         let mut sig_bytes = [0u8; SIGNATURE_LENGTH]; | ||||||
|             .map_err(VeilidAPIError::internal)?; |         sig_bytes[0..32].copy_from_slice(&in_sig_bytes[0..32]); | ||||||
|  |         sig_bytes[32..64].copy_from_slice(&do_xor_32(&in_sig_bytes[32..64], &dht_key_secret.bytes)); | ||||||
|         let dht_sig = Signature::new(sig.to_bytes()); |         let dht_sig = Signature::new(sig_bytes.into()); | ||||||
|         Ok(dht_sig) |         Ok(dht_sig) | ||||||
|     } |     } | ||||||
|     fn verify( |     fn verify( | ||||||
| @@ -178,16 +179,29 @@ impl CryptoSystem for CryptoSystemVLD0 { | |||||||
|         data: &[u8], |         data: &[u8], | ||||||
|         signature: &Signature, |         signature: &Signature, | ||||||
|     ) -> Result<(), VeilidAPIError> { |     ) -> Result<(), VeilidAPIError> { | ||||||
|         let pk = ed::PublicKey::from_bytes(&dht_key.bytes) |  | ||||||
|             .map_err(|e| VeilidAPIError::parse_error("Public key is invalid", e))?; |  | ||||||
|         let sig = ed::Signature::from_bytes(&signature.bytes) |  | ||||||
|             .map_err(|e| VeilidAPIError::parse_error("Signature is invalid", e))?; |  | ||||||
|  |  | ||||||
|         let mut dig = Blake3Digest512::new(); |         let mut dig = Blake3Digest512::new(); | ||||||
|         dig.update(data); |         dig.update(data); | ||||||
|  |         let sig = dig.finalize(); | ||||||
|  |         let in_sig_bytes: [u8; SIGNATURE_LENGTH] = sig.into(); | ||||||
|  |         let mut verify_bytes = [0u8; SIGNATURE_LENGTH]; | ||||||
|  |         verify_bytes[0..32] | ||||||
|  |             .copy_from_slice(&do_xor_32(&in_sig_bytes[0..32], &signature.bytes[0..32])); | ||||||
|  |         verify_bytes[32..64] | ||||||
|  |             .copy_from_slice(&do_xor_32(&in_sig_bytes[32..64], &signature.bytes[32..64])); | ||||||
|  |  | ||||||
|  |         if !is_bytes_eq_32(&verify_bytes[0..32], 0u8) { | ||||||
|  |             return Err(VeilidAPIError::parse_error( | ||||||
|  |                 "Verification failed", | ||||||
|  |                 "signature 0..32 is invalid", | ||||||
|  |             )); | ||||||
|  |         } | ||||||
|  |         if !is_bytes_eq_32(&do_xor_32(&verify_bytes[32..64], &dht_key.bytes), 0xFFu8) { | ||||||
|  |             return Err(VeilidAPIError::parse_error( | ||||||
|  |                 "Verification failed", | ||||||
|  |                 "signature 32..64 is invalid", | ||||||
|  |             )); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         pk.verify_prehashed(dig, None, &sig) |  | ||||||
|             .map_err(|e| VeilidAPIError::parse_error("Verification failed", e))?; |  | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -200,14 +214,21 @@ impl CryptoSystem for CryptoSystemVLD0 { | |||||||
|         body: &mut Vec<u8>, |         body: &mut Vec<u8>, | ||||||
|         nonce: &Nonce, |         nonce: &Nonce, | ||||||
|         shared_secret: &SharedSecret, |         shared_secret: &SharedSecret, | ||||||
|         associated_data: Option<&[u8]>, |         _associated_data: Option<&[u8]>, | ||||||
|     ) -> Result<(), VeilidAPIError> { |     ) -> Result<(), VeilidAPIError> { | ||||||
|         let key = ch::Key::from(shared_secret.bytes); |         let mut blob = nonce.bytes.to_vec(); | ||||||
|         let xnonce = ch::XNonce::from(nonce.bytes); |         blob.extend_from_slice(&[0u8; 8]); | ||||||
|         let aead = ch::XChaCha20Poly1305::new(&key); |         let blob = do_xor_32(&blob, &shared_secret.bytes); | ||||||
|         aead.decrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body) |  | ||||||
|             .map_err(map_to_string) |         if body.len() < AEAD_OVERHEAD { | ||||||
|             .map_err(VeilidAPIError::generic) |             return Err(VeilidAPIError::generic("invalid length")); | ||||||
|  |         } | ||||||
|  |         if &body[body.len() - AEAD_OVERHEAD..] != &blob { | ||||||
|  |             return Err(VeilidAPIError::generic("invalid keyblob")); | ||||||
|  |         } | ||||||
|  |         body.truncate(body.len() - AEAD_OVERHEAD); | ||||||
|  |         do_xor_inplace(body, &blob); | ||||||
|  |         Ok(()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn decrypt_aead( |     fn decrypt_aead( | ||||||
| @@ -229,15 +250,14 @@ impl CryptoSystem for CryptoSystemVLD0 { | |||||||
|         body: &mut Vec<u8>, |         body: &mut Vec<u8>, | ||||||
|         nonce: &Nonce, |         nonce: &Nonce, | ||||||
|         shared_secret: &SharedSecret, |         shared_secret: &SharedSecret, | ||||||
|         associated_data: Option<&[u8]>, |         _associated_data: Option<&[u8]>, | ||||||
|     ) -> Result<(), VeilidAPIError> { |     ) -> Result<(), VeilidAPIError> { | ||||||
|         let key = ch::Key::from(shared_secret.bytes); |         let mut blob = nonce.bytes.to_vec(); | ||||||
|         let xnonce = ch::XNonce::from(nonce.bytes); |         blob.extend_from_slice(&[0u8; 8]); | ||||||
|         let aead = ch::XChaCha20Poly1305::new(&key); |         let blob = do_xor_32(&blob, &shared_secret.bytes); | ||||||
|  |         do_xor_inplace(body, &blob); | ||||||
|         aead.encrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body) |         body.append(&mut blob.to_vec()); | ||||||
|             .map_err(map_to_string) |         Ok(()) | ||||||
|             .map_err(VeilidAPIError::generic) |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn encrypt_aead( |     fn encrypt_aead( | ||||||
| @@ -261,8 +281,10 @@ impl CryptoSystem for CryptoSystemVLD0 { | |||||||
|         nonce: &Nonce, |         nonce: &Nonce, | ||||||
|         shared_secret: &SharedSecret, |         shared_secret: &SharedSecret, | ||||||
|     ) { |     ) { | ||||||
|         let mut cipher = XChaCha20::new(&shared_secret.bytes.into(), &nonce.bytes.into()); |         let mut blob = nonce.bytes.to_vec(); | ||||||
|         cipher.apply_keystream(body); |         blob.extend_from_slice(&[0u8; 8]); | ||||||
|  |         let blob = do_xor_32(&blob, &shared_secret.bytes); | ||||||
|  |         do_xor_inplace(body, &blob); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn crypt_b2b_no_auth( |     fn crypt_b2b_no_auth( | ||||||
| @@ -272,8 +294,10 @@ impl CryptoSystem for CryptoSystemVLD0 { | |||||||
|         nonce: &Nonce, |         nonce: &Nonce, | ||||||
|         shared_secret: &SharedSecret, |         shared_secret: &SharedSecret, | ||||||
|     ) { |     ) { | ||||||
|         let mut cipher = XChaCha20::new(&shared_secret.bytes.into(), &nonce.bytes.into()); |         let mut blob = nonce.bytes.to_vec(); | ||||||
|         cipher.apply_keystream_b2b(in_buf, out_buf).unwrap(); |         blob.extend_from_slice(&[0u8; 8]); | ||||||
|  |         let blob = do_xor_32(&blob, &shared_secret.bytes); | ||||||
|  |         do_xor_b2b(in_buf, out_buf, &blob); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn crypt_no_auth_aligned_8( |     fn crypt_no_auth_aligned_8( | ||||||
|   | |||||||
| @@ -55,20 +55,14 @@ pub async fn test_sign_and_verify(vcrypto: CryptoSystemVersion) { | |||||||
|     let a2 = vcrypto |     let a2 = vcrypto | ||||||
|         .sign(&dht_key2, &dht_key_secret2, LOREM_IPSUM.as_bytes()) |         .sign(&dht_key2, &dht_key_secret2, LOREM_IPSUM.as_bytes()) | ||||||
|         .unwrap(); |         .unwrap(); | ||||||
|     let b1 = vcrypto |     let _b1 = vcrypto | ||||||
|         .sign(&dht_key, &dht_key_secret2, LOREM_IPSUM.as_bytes()) |         .sign(&dht_key, &dht_key_secret2, LOREM_IPSUM.as_bytes()) | ||||||
|         .unwrap(); |         .unwrap_err(); | ||||||
|     let b2 = vcrypto |     let _b2 = vcrypto | ||||||
|         .sign(&dht_key2, &dht_key_secret, LOREM_IPSUM.as_bytes()) |         .sign(&dht_key2, &dht_key_secret, LOREM_IPSUM.as_bytes()) | ||||||
|         .unwrap(); |         .unwrap_err(); | ||||||
|     assert_ne!(a1, b1); |  | ||||||
|     assert_ne!(a2, b2); |  | ||||||
|     assert_ne!(a1, b2); |  | ||||||
|     assert_ne!(a2, b1); |  | ||||||
|     assert_ne!(a1, a2); |     assert_ne!(a1, a2); | ||||||
|     assert_ne!(b1, b2); |  | ||||||
|     assert_ne!(a1, b2); |  | ||||||
|     assert_ne!(b1, a2); |  | ||||||
|  |  | ||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         vcrypto.verify(&dht_key, LOREM_IPSUM.as_bytes(), &a1), |         vcrypto.verify(&dht_key, LOREM_IPSUM.as_bytes(), &a1), | ||||||
| @@ -79,10 +73,10 @@ pub async fn test_sign_and_verify(vcrypto: CryptoSystemVersion) { | |||||||
|         Ok(()) |         Ok(()) | ||||||
|     ); |     ); | ||||||
|     assert!(vcrypto |     assert!(vcrypto | ||||||
|         .verify(&dht_key, LOREM_IPSUM.as_bytes(), &b1) |         .verify(&dht_key, LOREM_IPSUM.as_bytes(), &a2) | ||||||
|         .is_err()); |         .is_err()); | ||||||
|     assert!(vcrypto |     assert!(vcrypto | ||||||
|         .verify(&dht_key2, LOREM_IPSUM.as_bytes(), &b2) |         .verify(&dht_key2, LOREM_IPSUM.as_bytes(), &a1) | ||||||
|         .is_err()); |         .is_err()); | ||||||
|  |  | ||||||
|     // Try verifications that should work |     // Try verifications that should work | ||||||
|   | |||||||
| @@ -1,70 +0,0 @@ | |||||||
| use digest::generic_array::typenum::U64; |  | ||||||
| use digest::{Digest, Output}; |  | ||||||
| use generic_array::GenericArray; |  | ||||||
|  |  | ||||||
| pub struct Blake3Digest512 { |  | ||||||
|     dig: blake3::Hasher, |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl Digest for Blake3Digest512 { |  | ||||||
|     type OutputSize = U64; |  | ||||||
|  |  | ||||||
|     fn new() -> Self { |  | ||||||
|         Self { |  | ||||||
|             dig: blake3::Hasher::new(), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn update(&mut self, data: impl AsRef<[u8]>) { |  | ||||||
|         self.dig.update(data.as_ref()); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn chain(mut self, data: impl AsRef<[u8]>) -> Self |  | ||||||
|     where |  | ||||||
|         Self: Sized, |  | ||||||
|     { |  | ||||||
|         self.update(data); |  | ||||||
|         self |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn finalize(self) -> Output<Self> { |  | ||||||
|         let mut b = [0u8; 64]; |  | ||||||
|         self.dig.finalize_xof().fill(&mut b); |  | ||||||
|         let mut out = GenericArray::<u8, U64>::default(); |  | ||||||
|         for n in 0..64 { |  | ||||||
|             out[n] = b[n]; |  | ||||||
|         } |  | ||||||
|         out |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn finalize_reset(&mut self) -> Output<Self> { |  | ||||||
|         let mut b = [0u8; 64]; |  | ||||||
|         self.dig.finalize_xof().fill(&mut b); |  | ||||||
|         let mut out = GenericArray::<u8, U64>::default(); |  | ||||||
|         for n in 0..64 { |  | ||||||
|             out[n] = b[n]; |  | ||||||
|         } |  | ||||||
|         self.reset(); |  | ||||||
|         out |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn reset(&mut self) { |  | ||||||
|         self.dig.reset(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn output_size() -> usize { |  | ||||||
|         64 |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn digest(data: &[u8]) -> Output<Self> { |  | ||||||
|         let mut dig = blake3::Hasher::new(); |  | ||||||
|         dig.update(data); |  | ||||||
|         let mut b = [0u8; 64]; |  | ||||||
|         dig.finalize_xof().fill(&mut b); |  | ||||||
|         let mut out = GenericArray::<u8, U64>::default(); |  | ||||||
|         for n in 0..64 { |  | ||||||
|             out[n] = b[n]; |  | ||||||
|         } |  | ||||||
|         out |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,6 +1,3 @@ | |||||||
| pub mod blake3digest512; |  | ||||||
| pub use blake3digest512::*; |  | ||||||
|  |  | ||||||
| use super::*; | use super::*; | ||||||
|  |  | ||||||
| use chacha20::cipher::{KeyIvInit, StreamCipher}; | use chacha20::cipher::{KeyIvInit, StreamCipher}; | ||||||
| @@ -75,12 +72,12 @@ impl CryptoSystem for CryptoSystemVLD0 { | |||||||
|  |  | ||||||
|     // Generation |     // Generation | ||||||
|     fn random_nonce(&self) -> Nonce { |     fn random_nonce(&self) -> Nonce { | ||||||
|         let mut nonce = [0u8; 24]; |         let mut nonce = [0u8; NONCE_LENGTH]; | ||||||
|         random_bytes(&mut nonce).unwrap(); |         random_bytes(&mut nonce).unwrap(); | ||||||
|         Nonce::new(nonce) |         Nonce::new(nonce) | ||||||
|     } |     } | ||||||
|     fn random_shared_secret(&self) -> SharedSecret { |     fn random_shared_secret(&self) -> SharedSecret { | ||||||
|         let mut s = [0u8; 32]; |         let mut s = [0u8; SHARED_SECRET_LENGTH]; | ||||||
|         random_bytes(&mut s).unwrap(); |         random_bytes(&mut s).unwrap(); | ||||||
|         SharedSecret::new(s) |         SharedSecret::new(s) | ||||||
|     } |     } | ||||||
| @@ -165,12 +162,15 @@ impl CryptoSystem for CryptoSystemVLD0 { | |||||||
|         let mut dig = Blake3Digest512::new(); |         let mut dig = Blake3Digest512::new(); | ||||||
|         dig.update(data); |         dig.update(data); | ||||||
|  |  | ||||||
|         let sig = keypair |         let sig_bytes = keypair | ||||||
|             .sign_prehashed(dig, None) |             .sign_prehashed(dig, None) | ||||||
|             .map_err(VeilidAPIError::internal)?; |             .map_err(VeilidAPIError::internal)?; | ||||||
|  |  | ||||||
|         let dht_sig = Signature::new(sig.to_bytes()); |         let sig = Signature::new(sig_bytes.to_bytes()); | ||||||
|         Ok(dht_sig) |  | ||||||
|  |         self.verify(dht_key, &data, &sig)?; | ||||||
|  |  | ||||||
|  |         Ok(sig) | ||||||
|     } |     } | ||||||
|     fn verify( |     fn verify( | ||||||
|         &self, |         &self, | ||||||
|   | |||||||
| @@ -35,7 +35,6 @@ mod veilid_layer_filter; | |||||||
|  |  | ||||||
| pub use self::api_tracing_layer::ApiTracingLayer; | pub use self::api_tracing_layer::ApiTracingLayer; | ||||||
| pub use self::core_context::{api_startup, api_startup_json, UpdateCallback}; | 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_api::*; | ||||||
| pub use self::veilid_config::*; | pub use self::veilid_config::*; | ||||||
| pub use self::veilid_layer_filter::*; | pub use self::veilid_layer_filter::*; | ||||||
|   | |||||||
| @@ -919,8 +919,99 @@ impl VeilidConfig { | |||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Get the node id from config if one is specified |     #[cfg(not(test))] | ||||||
|     // Must be done -after- protected store startup |     async fn init_node_id( | ||||||
|  |         &self, | ||||||
|  |         vcrypto: CryptoSystemVersion, | ||||||
|  |         protected_store: intf::ProtectedStore, | ||||||
|  |     ) -> Result<(TypedKey, TypedSecret), VeilidAPIError> { | ||||||
|  |         let ck = vcrypto.kind(); | ||||||
|  |         let mut node_id = self.inner.read().network.routing_table.node_id.get(ck); | ||||||
|  |         let mut node_id_secret = self | ||||||
|  |             .inner | ||||||
|  |             .read() | ||||||
|  |             .network | ||||||
|  |             .routing_table | ||||||
|  |             .node_id_secret | ||||||
|  |             .get(ck); | ||||||
|  |  | ||||||
|  |         // See if node id was previously stored in the protected store | ||||||
|  |         if node_id.is_none() { | ||||||
|  |             debug!("pulling node_id_{} from storage", ck); | ||||||
|  |             if let Some(s) = protected_store | ||||||
|  |                 .load_user_secret_string(format!("node_id_{}", ck)) | ||||||
|  |                 .await | ||||||
|  |                 .map_err(VeilidAPIError::internal)? | ||||||
|  |             { | ||||||
|  |                 debug!("node_id_{} found in storage", ck); | ||||||
|  |                 node_id = match TypedKey::from_str(s.as_str()) { | ||||||
|  |                     Ok(v) => Some(v), | ||||||
|  |                     Err(_) => { | ||||||
|  |                         debug!("node id in protected store is not valid"); | ||||||
|  |                         None | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 debug!("node_id_{} not found in storage", ck); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // See if node id secret was previously stored in the protected store | ||||||
|  |         if node_id_secret.is_none() { | ||||||
|  |             debug!("pulling node id secret from storage"); | ||||||
|  |             if let Some(s) = protected_store | ||||||
|  |                 .load_user_secret_string(format!("node_id_secret_{}", ck)) | ||||||
|  |                 .await | ||||||
|  |                 .map_err(VeilidAPIError::internal)? | ||||||
|  |             { | ||||||
|  |                 debug!("node_id_secret_{} found in storage", ck); | ||||||
|  |                 node_id_secret = match TypedSecret::from_str(s.as_str()) { | ||||||
|  |                     Ok(v) => Some(v), | ||||||
|  |                     Err(_) => { | ||||||
|  |                         debug!("node id secret in protected store is not valid"); | ||||||
|  |                         None | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 debug!("node_id_secret_{} not found in storage", ck); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // If we have a node id from storage, check it | ||||||
|  |         let (node_id, node_id_secret) = | ||||||
|  |             if let (Some(node_id), Some(node_id_secret)) = (node_id, node_id_secret) { | ||||||
|  |                 // Validate node id | ||||||
|  |                 if !vcrypto.validate_keypair(&node_id.value, &node_id_secret.value) { | ||||||
|  |                     apibail_generic!(format!( | ||||||
|  |                         "node_id_secret_{} and node_id_key_{} don't match", | ||||||
|  |                         ck, ck | ||||||
|  |                     )); | ||||||
|  |                 } | ||||||
|  |                 (node_id, node_id_secret) | ||||||
|  |             } else { | ||||||
|  |                 // If we still don't have a valid node id, generate one | ||||||
|  |                 debug!("generating new node_id_{}", ck); | ||||||
|  |                 let kp = vcrypto.generate_keypair(); | ||||||
|  |                 (TypedKey::new(ck, kp.key), TypedSecret::new(ck, kp.secret)) | ||||||
|  |             }; | ||||||
|  |         info!("Node Id: {}", node_id); | ||||||
|  |  | ||||||
|  |         // Save the node id / secret in storage | ||||||
|  |         protected_store | ||||||
|  |             .save_user_secret_string(format!("node_id_{}", ck), node_id.to_string()) | ||||||
|  |             .await | ||||||
|  |             .map_err(VeilidAPIError::internal)?; | ||||||
|  |         protected_store | ||||||
|  |             .save_user_secret_string(format!("node_id_secret_{}", ck), node_id_secret.to_string()) | ||||||
|  |             .await | ||||||
|  |             .map_err(VeilidAPIError::internal)?; | ||||||
|  |  | ||||||
|  |         Ok((node_id, node_id_secret)) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// Get the node id from config if one is specified | ||||||
|  |     /// Must be done -after- protected store startup | ||||||
|  |     #[cfg_attr(test, allow(unused_variables))] | ||||||
|     pub async fn init_node_ids( |     pub async fn init_node_ids( | ||||||
|         &self, |         &self, | ||||||
|         crypto: Crypto, |         crypto: Crypto, | ||||||
| @@ -934,88 +1025,14 @@ impl VeilidConfig { | |||||||
|                 .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.inner.read().network.routing_table.node_id.get(ck); |             #[cfg(test)] | ||||||
|             let mut node_id_secret = self |             let (node_id, node_id_secret) = { | ||||||
|                 .inner |                 let kp = vcrypto.generate_keypair(); | ||||||
|                 .read() |                 (TypedKey::new(ck, kp.key), TypedSecret::new(ck, kp.secret)) | ||||||
|                 .network |             }; | ||||||
|                 .routing_table |             #[cfg(not(test))] | ||||||
|                 .node_id_secret |  | ||||||
|                 .get(ck); |  | ||||||
|  |  | ||||||
|             // See if node id was previously stored in the protected store |  | ||||||
|             if node_id.is_none() { |  | ||||||
|                 debug!("pulling node_id_{} from storage", ck); |  | ||||||
|                 if let Some(s) = protected_store |  | ||||||
|                     .load_user_secret_string(format!("node_id_{}", ck)) |  | ||||||
|                     .await |  | ||||||
|                     .map_err(VeilidAPIError::internal)? |  | ||||||
|                 { |  | ||||||
|                     debug!("node_id_{} found in storage", ck); |  | ||||||
|                     node_id = match TypedKey::from_str(s.as_str()) { |  | ||||||
|                         Ok(v) => Some(v), |  | ||||||
|                         Err(_) => { |  | ||||||
|                             debug!("node id in protected store is not valid"); |  | ||||||
|                             None |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     debug!("node_id_{} not found in storage", ck); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             // See if node id secret was previously stored in the protected store |  | ||||||
|             if node_id_secret.is_none() { |  | ||||||
|                 debug!("pulling node id secret from storage"); |  | ||||||
|                 if let Some(s) = protected_store |  | ||||||
|                     .load_user_secret_string(format!("node_id_secret_{}", ck)) |  | ||||||
|                     .await |  | ||||||
|                     .map_err(VeilidAPIError::internal)? |  | ||||||
|                 { |  | ||||||
|                     debug!("node_id_secret_{} found in storage", ck); |  | ||||||
|                     node_id_secret = match TypedSecret::from_str(s.as_str()) { |  | ||||||
|                         Ok(v) => Some(v), |  | ||||||
|                         Err(_) => { |  | ||||||
|                             debug!("node id secret in protected store is not valid"); |  | ||||||
|                             None |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     debug!("node_id_secret_{} not found in storage", ck); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             // If we have a node id from storage, check it |  | ||||||
|             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) { |                 self.init_node_id(vcrypto, protected_store.clone()).await?; | ||||||
|                     // Validate node id |  | ||||||
|                     if !vcrypto.validate_keypair(&node_id.value, &node_id_secret.value) { |  | ||||||
|                         apibail_generic!(format!( |  | ||||||
|                             "node_id_secret_{} and node_id_key_{} don't match", |  | ||||||
|                             ck, ck |  | ||||||
|                         )); |  | ||||||
|                     } |  | ||||||
|                     (node_id, node_id_secret) |  | ||||||
|                 } else { |  | ||||||
|                     // If we still don't have a valid node id, generate one |  | ||||||
|                     debug!("generating new node_id_{}", ck); |  | ||||||
|                     let kp = vcrypto.generate_keypair(); |  | ||||||
|                     (TypedKey::new(ck, kp.key), TypedSecret::new(ck, kp.secret)) |  | ||||||
|                 }; |  | ||||||
|             info!("Node Id: {}", node_id); |  | ||||||
|  |  | ||||||
|             // Save the node id / secret in storage |  | ||||||
|             protected_store |  | ||||||
|                 .save_user_secret_string(format!("node_id_{}", ck), node_id.to_string()) |  | ||||||
|                 .await |  | ||||||
|                 .map_err(VeilidAPIError::internal)?; |  | ||||||
|             protected_store |  | ||||||
|                 .save_user_secret_string( |  | ||||||
|                     format!("node_id_secret_{}", ck), |  | ||||||
|                     node_id_secret.to_string(), |  | ||||||
|                 ) |  | ||||||
|                 .await |  | ||||||
|                 .map_err(VeilidAPIError::internal)?; |  | ||||||
|  |  | ||||||
|             // Save for config |             // Save for config | ||||||
|             out_node_id.add(node_id); |             out_node_id.add(node_id); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user