refactor network manager
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
pub mod crypto;
|
||||
pub mod envelope;
|
||||
pub mod key;
|
||||
pub mod receipt;
|
||||
pub mod value;
|
||||
mod crypto;
|
||||
mod envelope;
|
||||
mod key;
|
||||
mod receipt;
|
||||
mod value;
|
||||
|
||||
pub mod tests;
|
||||
|
||||
pub use crypto::*;
|
||||
pub use envelope::*;
|
||||
|
5
veilid-core/src/dht/tests/mod.rs
Normal file
5
veilid-core/src/dht/tests/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
pub mod test_crypto;
|
||||
pub mod test_dht_key;
|
||||
pub mod test_envelope_receipt;
|
||||
|
||||
use super::*;
|
175
veilid-core/src/dht/tests/test_crypto.rs
Normal file
175
veilid-core/src/dht/tests/test_crypto.rs
Normal file
@@ -0,0 +1,175 @@
|
||||
use super::*;
|
||||
use crate::tests::common::test_veilid_config::*;
|
||||
use crate::xx::*;
|
||||
use crate::*;
|
||||
|
||||
static LOREM_IPSUM:&[u8] = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ";
|
||||
|
||||
async fn startup() -> VeilidAPI {
|
||||
trace!("test_table_store: starting");
|
||||
let (update_callback, config_callback) = setup_veilid_core();
|
||||
let api = api_startup(update_callback, config_callback)
|
||||
.await
|
||||
.expect("startup failed");
|
||||
api
|
||||
}
|
||||
|
||||
async fn shutdown(api: VeilidAPI) {
|
||||
trace!("test_table_store: shutting down");
|
||||
api.shutdown().await;
|
||||
trace!("test_table_store: finished");
|
||||
}
|
||||
|
||||
pub async fn test_aead() {
|
||||
trace!("test_aead");
|
||||
|
||||
let n1 = Crypto::get_random_nonce();
|
||||
let n2 = loop {
|
||||
let n = Crypto::get_random_nonce();
|
||||
if n != n1 {
|
||||
break n;
|
||||
}
|
||||
};
|
||||
|
||||
let ss1 = Crypto::get_random_secret();
|
||||
let ss2 = loop {
|
||||
let ss = Crypto::get_random_secret();
|
||||
if ss != ss1 {
|
||||
break ss;
|
||||
}
|
||||
};
|
||||
|
||||
let mut body = LOREM_IPSUM.to_vec();
|
||||
let body2 = body.clone();
|
||||
let size_before_encrypt = body.len();
|
||||
assert!(
|
||||
Crypto::encrypt_in_place_aead(&mut body, &n1, &ss1, None).is_ok(),
|
||||
"encrypt should succeed"
|
||||
);
|
||||
let size_after_encrypt = body.len();
|
||||
assert!(
|
||||
size_after_encrypt - size_before_encrypt == AEAD_OVERHEAD,
|
||||
"overhead should match"
|
||||
);
|
||||
let mut body3 = body.clone();
|
||||
let mut body4 = body.clone();
|
||||
let mut body5 = body.clone();
|
||||
assert!(
|
||||
Crypto::decrypt_in_place_aead(&mut body, &n1, &ss1, None).is_ok(),
|
||||
"decrypt should succeed"
|
||||
);
|
||||
assert_eq!(body, body2, "results should be the same");
|
||||
|
||||
assert!(
|
||||
Crypto::decrypt_in_place_aead(&mut body3, &n2, &ss1, None).is_err(),
|
||||
"decrypt with wrong nonce should fail"
|
||||
);
|
||||
assert_ne!(body3, body, "failure changes data");
|
||||
|
||||
assert!(
|
||||
Crypto::decrypt_in_place_aead(&mut body4, &n1, &ss2, None).is_err(),
|
||||
"decrypt with wrong secret should fail"
|
||||
);
|
||||
assert_ne!(body4, body, "failure changes data");
|
||||
|
||||
assert!(
|
||||
Crypto::decrypt_in_place_aead(&mut body5, &n1, &ss2, Some(b"foobar")).is_err(),
|
||||
"decrypt with wrong associated data should fail"
|
||||
);
|
||||
assert_ne!(body5, body, "failure changes data");
|
||||
|
||||
assert!(
|
||||
Crypto::decrypt_aead(LOREM_IPSUM, &n1, &ss1, None).is_err(),
|
||||
"should fail authentication"
|
||||
);
|
||||
|
||||
let body5 = Crypto::encrypt_aead(LOREM_IPSUM, &n1, &ss1, None).unwrap();
|
||||
let body6 = Crypto::decrypt_aead(&body5, &n1, &ss1, None).unwrap();
|
||||
let body7 = Crypto::encrypt_aead(LOREM_IPSUM, &n1, &ss1, None).unwrap();
|
||||
assert_eq!(body6, LOREM_IPSUM);
|
||||
assert_eq!(body5, body7);
|
||||
}
|
||||
|
||||
pub async fn test_no_auth() {
|
||||
trace!("test_no_auth");
|
||||
|
||||
let n1 = Crypto::get_random_nonce();
|
||||
let n2 = loop {
|
||||
let n = Crypto::get_random_nonce();
|
||||
if n != n1 {
|
||||
break n;
|
||||
}
|
||||
};
|
||||
|
||||
let ss1 = Crypto::get_random_secret();
|
||||
let ss2 = loop {
|
||||
let ss = Crypto::get_random_secret();
|
||||
if ss != ss1 {
|
||||
break ss;
|
||||
}
|
||||
};
|
||||
|
||||
let mut body = LOREM_IPSUM.to_vec();
|
||||
let body2 = body.clone();
|
||||
let size_before_encrypt = body.len();
|
||||
Crypto::crypt_in_place_no_auth(&mut body, &n1, &ss1);
|
||||
|
||||
let size_after_encrypt = body.len();
|
||||
assert_eq!(
|
||||
size_after_encrypt, size_before_encrypt,
|
||||
"overhead should match"
|
||||
);
|
||||
let mut body3 = body.clone();
|
||||
let mut body4 = body.clone();
|
||||
|
||||
Crypto::crypt_in_place_no_auth(&mut body, &n1, &ss1);
|
||||
assert_eq!(body, body2, "result after decrypt should be the same");
|
||||
|
||||
Crypto::crypt_in_place_no_auth(&mut body3, &n2, &ss1);
|
||||
assert_ne!(body3, body, "decrypt should not be equal with wrong nonce");
|
||||
|
||||
Crypto::crypt_in_place_no_auth(&mut body4, &n1, &ss2);
|
||||
assert_ne!(body4, body, "decrypt should not be equal with wrong secret");
|
||||
|
||||
let body5 = Crypto::crypt_no_auth(LOREM_IPSUM, &n1, &ss1);
|
||||
let body6 = Crypto::crypt_no_auth(&body5, &n1, &ss1);
|
||||
let body7 = Crypto::crypt_no_auth(LOREM_IPSUM, &n1, &ss1);
|
||||
assert_eq!(body6, LOREM_IPSUM);
|
||||
assert_eq!(body5, body7);
|
||||
}
|
||||
|
||||
pub async fn test_dh(crypto: Crypto) {
|
||||
trace!("test_dh");
|
||||
let (dht_key, dht_key_secret) = key::generate_secret();
|
||||
let (dht_key2, dht_key_secret2) = key::generate_secret();
|
||||
|
||||
let r1 = Crypto::compute_dh(&dht_key, &dht_key_secret2).unwrap();
|
||||
let r2 = Crypto::compute_dh(&dht_key2, &dht_key_secret).unwrap();
|
||||
let r3 = Crypto::compute_dh(&dht_key, &dht_key_secret2).unwrap();
|
||||
let r4 = Crypto::compute_dh(&dht_key2, &dht_key_secret).unwrap();
|
||||
assert_eq!(r1, r2);
|
||||
assert_eq!(r3, r4);
|
||||
assert_eq!(r2, r3);
|
||||
trace!("dh: {:?}", r1);
|
||||
|
||||
// test cache
|
||||
let r5 = crypto.cached_dh(&dht_key, &dht_key_secret2).unwrap();
|
||||
let r6 = crypto.cached_dh(&dht_key2, &dht_key_secret).unwrap();
|
||||
let r7 = crypto.cached_dh(&dht_key, &dht_key_secret2).unwrap();
|
||||
let r8 = crypto.cached_dh(&dht_key2, &dht_key_secret).unwrap();
|
||||
assert_eq!(r1, r5);
|
||||
assert_eq!(r2, r6);
|
||||
assert_eq!(r3, r7);
|
||||
assert_eq!(r4, r8);
|
||||
trace!("cached_dh: {:?}", r5);
|
||||
}
|
||||
|
||||
pub async fn test_all() {
|
||||
let api = startup().await;
|
||||
let crypto = api.crypto().unwrap();
|
||||
test_aead().await;
|
||||
test_no_auth().await;
|
||||
test_dh(crypto).await;
|
||||
shutdown(api.clone()).await;
|
||||
assert!(api.is_shutdown());
|
||||
}
|
325
veilid-core/src/dht/tests/test_dht_key.rs
Normal file
325
veilid-core/src/dht/tests/test_dht_key.rs
Normal file
@@ -0,0 +1,325 @@
|
||||
#![allow(clippy::bool_assert_comparison)]
|
||||
|
||||
use super::*;
|
||||
use crate::xx::*;
|
||||
use core::convert::TryFrom;
|
||||
|
||||
static LOREM_IPSUM:&str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ";
|
||||
static CHEEZBURGER: &str = "I can has cheezburger";
|
||||
static EMPTY_KEY: [u8; key::DHT_KEY_LENGTH] = [0u8; key::DHT_KEY_LENGTH];
|
||||
static EMPTY_KEY_SECRET: [u8; key::DHT_KEY_SECRET_LENGTH] = [0u8; key::DHT_KEY_SECRET_LENGTH];
|
||||
|
||||
pub async fn test_generate_secret() {
|
||||
// Verify keys generate
|
||||
let (dht_key, dht_key_secret) = key::generate_secret();
|
||||
let (dht_key2, dht_key_secret2) = key::generate_secret();
|
||||
|
||||
// Verify byte patterns are different between public and secret
|
||||
assert_ne!(dht_key.bytes, dht_key_secret.bytes);
|
||||
assert_ne!(dht_key2.bytes, dht_key_secret2.bytes);
|
||||
|
||||
// Verify the keys and secrets are different across keypairs
|
||||
assert_ne!(dht_key, dht_key2);
|
||||
assert_ne!(dht_key_secret, dht_key_secret2);
|
||||
}
|
||||
|
||||
pub async fn test_sign_and_verify() {
|
||||
// Make two keys
|
||||
let (dht_key, dht_key_secret) = key::generate_secret();
|
||||
let (dht_key2, dht_key_secret2) = key::generate_secret();
|
||||
// Sign the same message twice
|
||||
let dht_sig = key::sign(&dht_key, &dht_key_secret, LOREM_IPSUM.as_bytes()).unwrap();
|
||||
trace!("dht_sig: {:?}", dht_sig);
|
||||
let dht_sig_b = key::sign(&dht_key, &dht_key_secret, LOREM_IPSUM.as_bytes()).unwrap();
|
||||
// Sign a second message
|
||||
let dht_sig_c = key::sign(&dht_key, &dht_key_secret, CHEEZBURGER.as_bytes()).unwrap();
|
||||
trace!("dht_sig_c: {:?}", dht_sig_c);
|
||||
// Verify they are the same signature
|
||||
assert_eq!(dht_sig, dht_sig_b);
|
||||
// Sign the same message with a different key
|
||||
let dht_sig2 = key::sign(&dht_key2, &dht_key_secret2, LOREM_IPSUM.as_bytes()).unwrap();
|
||||
// Verify a different key gives a different signature
|
||||
assert_ne!(dht_sig2, dht_sig_b);
|
||||
|
||||
// Try using the wrong secret to sign
|
||||
let a1 = key::sign(&dht_key, &dht_key_secret, LOREM_IPSUM.as_bytes()).unwrap();
|
||||
let a2 = key::sign(&dht_key2, &dht_key_secret2, LOREM_IPSUM.as_bytes()).unwrap();
|
||||
let b1 = key::sign(&dht_key, &dht_key_secret2, LOREM_IPSUM.as_bytes()).unwrap();
|
||||
let b2 = key::sign(&dht_key2, &dht_key_secret, LOREM_IPSUM.as_bytes()).unwrap();
|
||||
assert_ne!(a1, b1);
|
||||
assert_ne!(a2, b2);
|
||||
assert_ne!(a1, b2);
|
||||
assert_ne!(a2, b1);
|
||||
assert_ne!(a1, a2);
|
||||
assert_ne!(b1, b2);
|
||||
assert_ne!(a1, b2);
|
||||
assert_ne!(b1, a2);
|
||||
|
||||
assert_eq!(key::verify(&dht_key, LOREM_IPSUM.as_bytes(), &a1), Ok(()));
|
||||
assert_eq!(key::verify(&dht_key2, LOREM_IPSUM.as_bytes(), &a2), Ok(()));
|
||||
assert_eq!(
|
||||
key::verify(&dht_key, LOREM_IPSUM.as_bytes(), &b1),
|
||||
Err("Verification failed".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
key::verify(&dht_key2, LOREM_IPSUM.as_bytes(), &b2),
|
||||
Err("Verification failed".to_owned())
|
||||
);
|
||||
|
||||
// Try verifications that should work
|
||||
assert_eq!(
|
||||
key::verify(&dht_key, LOREM_IPSUM.as_bytes(), &dht_sig),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(
|
||||
key::verify(&dht_key, LOREM_IPSUM.as_bytes(), &dht_sig_b),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(
|
||||
key::verify(&dht_key2, LOREM_IPSUM.as_bytes(), &dht_sig2),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(
|
||||
key::verify(&dht_key, CHEEZBURGER.as_bytes(), &dht_sig_c),
|
||||
Ok(())
|
||||
);
|
||||
// Try verifications that shouldn't work
|
||||
assert_eq!(
|
||||
key::verify(&dht_key2, LOREM_IPSUM.as_bytes(), &dht_sig),
|
||||
Err("Verification failed".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
key::verify(&dht_key, LOREM_IPSUM.as_bytes(), &dht_sig2),
|
||||
Err("Verification failed".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
key::verify(&dht_key2, CHEEZBURGER.as_bytes(), &dht_sig_c),
|
||||
Err("Verification failed".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
key::verify(&dht_key, CHEEZBURGER.as_bytes(), &dht_sig),
|
||||
Err("Verification failed".to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
pub async fn test_key_conversions() {
|
||||
// Test default key
|
||||
let (dht_key, dht_key_secret) = (key::DHTKey::default(), key::DHTKeySecret::default());
|
||||
assert_eq!(dht_key.bytes, EMPTY_KEY);
|
||||
assert!(!dht_key.valid);
|
||||
assert_eq!(dht_key_secret.bytes, EMPTY_KEY_SECRET);
|
||||
assert!(!dht_key_secret.valid);
|
||||
let dht_key_string = String::from(&dht_key);
|
||||
trace!("dht_key_string: {:?}", dht_key_string);
|
||||
let dht_key_string2 = String::from(&dht_key);
|
||||
trace!("dht_key_string2: {:?}", dht_key_string2);
|
||||
assert_eq!(dht_key_string, dht_key_string2);
|
||||
|
||||
let dht_key_secret_string = String::from(&dht_key_secret);
|
||||
trace!("dht_key_secret_string: {:?}", dht_key_secret_string);
|
||||
assert_eq!(dht_key_secret_string, dht_key_string);
|
||||
|
||||
// Make different keys
|
||||
let (dht_key2, dht_key_secret2) = key::generate_secret();
|
||||
trace!("dht_key2: {:?}", dht_key2);
|
||||
trace!("dht_key_secret2: {:?}", dht_key_secret2);
|
||||
let (dht_key3, _dht_key_secret3) = key::generate_secret();
|
||||
trace!("dht_key3: {:?}", dht_key3);
|
||||
trace!("_dht_key_secret3: {:?}", _dht_key_secret3);
|
||||
|
||||
let dht_key2_string = String::from(&dht_key2);
|
||||
let dht_key2_string2 = String::from(&dht_key2);
|
||||
let dht_key3_string = String::from(&dht_key3);
|
||||
assert_eq!(dht_key2_string, dht_key2_string2);
|
||||
assert_ne!(dht_key3_string, dht_key2_string);
|
||||
let dht_key_secret2_string = String::from(&dht_key_secret2);
|
||||
assert_ne!(dht_key_secret2_string, dht_key_secret_string);
|
||||
assert_ne!(dht_key_secret2_string, dht_key2_string);
|
||||
|
||||
// Assert they convert back correctly
|
||||
let dht_key_back = key::DHTKey::try_from(dht_key_string.as_str()).unwrap();
|
||||
let dht_key_back2 = key::DHTKey::try_from(dht_key_string2.as_str()).unwrap();
|
||||
assert_eq!(dht_key_back, dht_key_back2);
|
||||
assert_eq!(dht_key_back, dht_key);
|
||||
assert_eq!(dht_key_back2, dht_key);
|
||||
|
||||
let dht_key_secret_back = key::DHTKeySecret::try_from(dht_key_secret_string.as_str()).unwrap();
|
||||
assert_eq!(dht_key_secret_back, dht_key_secret);
|
||||
|
||||
let dht_key2_back = key::DHTKey::try_from(dht_key2_string.as_str()).unwrap();
|
||||
let dht_key2_back2 = key::DHTKey::try_from(dht_key2_string2.as_str()).unwrap();
|
||||
assert_eq!(dht_key2_back, dht_key2_back2);
|
||||
assert_eq!(dht_key2_back, dht_key2);
|
||||
assert_eq!(dht_key2_back2, dht_key2);
|
||||
|
||||
let dht_key_secret2_back =
|
||||
key::DHTKeySecret::try_from(dht_key_secret2_string.as_str()).unwrap();
|
||||
assert_eq!(dht_key_secret2_back, dht_key_secret2);
|
||||
|
||||
// Assert string roundtrip
|
||||
assert_eq!(String::from(&dht_key2_back), dht_key2_string);
|
||||
assert!(key::DHTKey::try_from("") == Ok(key::DHTKey::default()));
|
||||
assert!(key::DHTKeySecret::try_from("") == Ok(key::DHTKeySecret::default()));
|
||||
// These conversions should fail
|
||||
assert!(key::DHTKey::try_from("whatever").is_err());
|
||||
assert!(key::DHTKeySecret::try_from("whatever").is_err());
|
||||
assert!(key::DHTKey::try_from(" ").is_err());
|
||||
assert!(key::DHTKeySecret::try_from(" ").is_err());
|
||||
assert!(key::DHTKey::try_from(
|
||||
"qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"
|
||||
)
|
||||
.is_err());
|
||||
assert!(key::DHTKeySecret::try_from(
|
||||
"qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
pub async fn test_encode_decode() {
|
||||
let dht_key = key::DHTKey::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").unwrap();
|
||||
let dht_key_secret =
|
||||
key::DHTKeySecret::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").unwrap();
|
||||
let dht_key_b = key::DHTKey::new(EMPTY_KEY);
|
||||
let dht_key_secret_b = key::DHTKeySecret::new(EMPTY_KEY_SECRET);
|
||||
assert_eq!(dht_key, dht_key_b);
|
||||
assert_eq!(dht_key_secret, dht_key_secret_b);
|
||||
|
||||
let (dht_key2, dht_key_secret2) = key::generate_secret();
|
||||
|
||||
let e1 = dht_key.encode();
|
||||
trace!("e1: {:?}", e1);
|
||||
assert_eq!(e1, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA".to_owned());
|
||||
let e1s = dht_key_secret.encode();
|
||||
trace!("e1s: {:?}", e1s);
|
||||
let e2 = dht_key2.encode();
|
||||
trace!("e2: {:?}", e2);
|
||||
let e2s = dht_key_secret2.encode();
|
||||
trace!("e2s: {:?}", e2s);
|
||||
|
||||
let d1 = key::DHTKey::try_decode(e1.as_str()).unwrap();
|
||||
trace!("d1: {:?}", d1);
|
||||
assert_eq!(dht_key, d1);
|
||||
|
||||
let d1s = key::DHTKeySecret::try_decode(e1s.as_str()).unwrap();
|
||||
trace!("d1s: {:?}", d1s);
|
||||
assert_eq!(dht_key_secret, d1s);
|
||||
|
||||
let d2 = key::DHTKey::try_decode(e2.as_str()).unwrap();
|
||||
trace!("d2: {:?}", d2);
|
||||
assert_eq!(dht_key2, d2);
|
||||
|
||||
let d2s = key::DHTKeySecret::try_decode(e2s.as_str()).unwrap();
|
||||
trace!("d2s: {:?}", d2s);
|
||||
assert_eq!(dht_key_secret2, d2s);
|
||||
|
||||
// Failures
|
||||
let f1 = key::DHTKeySecret::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
assert_eq!(f1, Err("Incorrect length in decode".to_owned()));
|
||||
let f2 = key::DHTKeySecret::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&");
|
||||
assert_eq!(f2, Err("Failed to decode".to_owned()));
|
||||
}
|
||||
|
||||
async fn test_hash() {
|
||||
let mut s = BTreeSet::<key::DHTKey>::new();
|
||||
|
||||
let k1 = key::generate_hash("abc".as_bytes());
|
||||
let k2 = key::generate_hash("abcd".as_bytes());
|
||||
let k3 = key::generate_hash("".as_bytes());
|
||||
let k4 = key::generate_hash(" ".as_bytes());
|
||||
let k5 = key::generate_hash(LOREM_IPSUM.as_bytes());
|
||||
let k6 = key::generate_hash(CHEEZBURGER.as_bytes());
|
||||
|
||||
s.insert(k1);
|
||||
s.insert(k2);
|
||||
s.insert(k3);
|
||||
s.insert(k4);
|
||||
s.insert(k5);
|
||||
s.insert(k6);
|
||||
assert_eq!(s.len(), 6);
|
||||
|
||||
let v1 = key::generate_hash("abc".as_bytes());
|
||||
let v2 = key::generate_hash("abcd".as_bytes());
|
||||
let v3 = key::generate_hash("".as_bytes());
|
||||
let v4 = key::generate_hash(" ".as_bytes());
|
||||
let v5 = key::generate_hash(LOREM_IPSUM.as_bytes());
|
||||
let v6 = key::generate_hash(CHEEZBURGER.as_bytes());
|
||||
|
||||
assert_eq!(k1, v1);
|
||||
assert_eq!(k2, v2);
|
||||
assert_eq!(k3, v3);
|
||||
assert_eq!(k4, v4);
|
||||
assert_eq!(k5, v5);
|
||||
assert_eq!(k6, v6);
|
||||
|
||||
key::validate_hash("abc".as_bytes(), &v1);
|
||||
key::validate_hash("abcd".as_bytes(), &v2);
|
||||
key::validate_hash("".as_bytes(), &v3);
|
||||
key::validate_hash(" ".as_bytes(), &v4);
|
||||
key::validate_hash(LOREM_IPSUM.as_bytes(), &v5);
|
||||
key::validate_hash(CHEEZBURGER.as_bytes(), &v6);
|
||||
}
|
||||
|
||||
async fn test_operations() {
|
||||
let k1 = key::generate_hash(LOREM_IPSUM.as_bytes());
|
||||
let k2 = key::generate_hash(CHEEZBURGER.as_bytes());
|
||||
let k3 = key::generate_hash("abc".as_bytes());
|
||||
|
||||
// Get distance
|
||||
let d1 = key::distance(&k1, &k2);
|
||||
let d2 = key::distance(&k2, &k1);
|
||||
let d3 = key::distance(&k1, &k3);
|
||||
let d4 = key::distance(&k2, &k3);
|
||||
|
||||
trace!("d1={:?}", d1);
|
||||
trace!("d2={:?}", d2);
|
||||
trace!("d3={:?}", d3);
|
||||
trace!("d4={:?}", d4);
|
||||
|
||||
// Verify commutativity
|
||||
assert_eq!(d1, d2);
|
||||
assert!(d1 <= d2);
|
||||
assert!(d1 >= d2);
|
||||
assert!(d1 >= d2);
|
||||
assert!(d1 <= d2);
|
||||
assert_eq!(d2, d1);
|
||||
assert!(d2 <= d1);
|
||||
assert!(d2 >= d1);
|
||||
assert!(d2 >= d1);
|
||||
assert!(d2 <= d1);
|
||||
|
||||
// Verify nibbles
|
||||
assert_eq!(d1.nibble(0), 0x9u8);
|
||||
assert_eq!(d1.nibble(1), 0x4u8);
|
||||
assert_eq!(d1.nibble(2), 0x3u8);
|
||||
assert_eq!(d1.nibble(3), 0x6u8);
|
||||
assert_eq!(d1.nibble(63), 0x6u8);
|
||||
|
||||
assert_eq!(d1.first_nonzero_nibble(), Some((0, 0x9u8)));
|
||||
assert_eq!(d2.first_nonzero_nibble(), Some((0, 0x9u8)));
|
||||
assert_eq!(d3.first_nonzero_nibble(), Some((1, 0x4u8)));
|
||||
assert_eq!(d4.first_nonzero_nibble(), Some((0, 0x9u8)));
|
||||
|
||||
// Verify bits
|
||||
assert_eq!(d1.bit(0), true);
|
||||
assert_eq!(d1.bit(1), false);
|
||||
assert_eq!(d1.bit(7), false);
|
||||
assert_eq!(d1.bit(8), false);
|
||||
assert_eq!(d1.bit(14), true);
|
||||
assert_eq!(d1.bit(15), false);
|
||||
assert_eq!(d1.bit(254), true);
|
||||
assert_eq!(d1.bit(255), false);
|
||||
|
||||
assert_eq!(d1.first_nonzero_bit(), Some(0));
|
||||
assert_eq!(d2.first_nonzero_bit(), Some(0));
|
||||
assert_eq!(d3.first_nonzero_bit(), Some(5));
|
||||
assert_eq!(d4.first_nonzero_bit(), Some(0));
|
||||
}
|
||||
|
||||
pub async fn test_all() {
|
||||
test_generate_secret().await;
|
||||
test_sign_and_verify().await;
|
||||
test_key_conversions().await;
|
||||
test_encode_decode().await;
|
||||
test_hash().await;
|
||||
test_operations().await;
|
||||
}
|
92
veilid-core/src/dht/tests/test_envelope_receipt.rs
Normal file
92
veilid-core/src/dht/tests/test_envelope_receipt.rs
Normal file
@@ -0,0 +1,92 @@
|
||||
use super::*;
|
||||
use crate::tests::common::test_veilid_config::*;
|
||||
use crate::xx::*;
|
||||
use crate::*;
|
||||
|
||||
pub async fn test_envelope_round_trip() {
|
||||
info!("--- test envelope round trip ---");
|
||||
let (update_callback, config_callback) = setup_veilid_core();
|
||||
let api = api_startup(update_callback, config_callback)
|
||||
.await
|
||||
.expect("startup failed");
|
||||
|
||||
// Get crypto
|
||||
let crypto = api.crypto().unwrap();
|
||||
|
||||
// Create envelope
|
||||
let ts = 0x12345678ABCDEF69u64;
|
||||
let nonce = Crypto::get_random_nonce();
|
||||
let (sender_id, sender_secret) = generate_secret();
|
||||
let (recipient_id, recipient_secret) = generate_secret();
|
||||
let envelope = Envelope::new(0, ts, nonce, sender_id, recipient_id);
|
||||
|
||||
// Create arbitrary body
|
||||
let body = b"This is an arbitrary body";
|
||||
|
||||
// Serialize to bytes
|
||||
let enc_data = envelope
|
||||
.to_encrypted_data(crypto.clone(), body, &sender_secret)
|
||||
.expect("failed to encrypt data");
|
||||
|
||||
// Deserialize from bytes
|
||||
let envelope2 =
|
||||
Envelope::from_signed_data(&enc_data).expect("failed to deserialize envelope from data");
|
||||
|
||||
let body2 = envelope2
|
||||
.decrypt_body(crypto.clone(), &enc_data, &recipient_secret)
|
||||
.expect("failed to decrypt envelope body");
|
||||
|
||||
// Compare envelope and body
|
||||
assert_eq!(envelope, envelope2);
|
||||
assert_eq!(body.to_vec(), body2);
|
||||
|
||||
// Deserialize from modified bytes
|
||||
let enc_data_len = enc_data.len();
|
||||
let mut mod_enc_data = enc_data.clone();
|
||||
mod_enc_data[enc_data_len - 1] ^= 0x80u8;
|
||||
assert!(
|
||||
Envelope::from_signed_data(&mod_enc_data).is_err(),
|
||||
"should have failed to decode envelope with modified signature"
|
||||
);
|
||||
let mut mod_enc_data2 = enc_data.clone();
|
||||
mod_enc_data2[enc_data_len - 65] ^= 0x80u8;
|
||||
assert!(
|
||||
Envelope::from_signed_data(&mod_enc_data2).is_err(),
|
||||
"should have failed to decode envelope with modified data"
|
||||
);
|
||||
|
||||
api.shutdown().await;
|
||||
}
|
||||
|
||||
pub async fn test_receipt_round_trip() {
|
||||
info!("--- test receipt round trip ---");
|
||||
// Create arbitrary body
|
||||
let body = b"This is an arbitrary body";
|
||||
|
||||
// Create receipt
|
||||
let nonce = Crypto::get_random_nonce();
|
||||
let (sender_id, sender_secret) = generate_secret();
|
||||
let receipt = Receipt::try_new(0, nonce, sender_id, body).expect("should not fail");
|
||||
|
||||
// Serialize to bytes
|
||||
let mut enc_data = receipt
|
||||
.to_signed_data(&sender_secret)
|
||||
.expect("failed to make signed data");
|
||||
|
||||
// Deserialize from bytes
|
||||
let receipt2 =
|
||||
Receipt::from_signed_data(&enc_data).expect("failed to deserialize envelope from data");
|
||||
|
||||
// Should not validate even when a single bit is changed
|
||||
enc_data[5] = 0x01;
|
||||
Receipt::from_signed_data(&enc_data)
|
||||
.expect_err("should have failed to decrypt using wrong secret");
|
||||
|
||||
// Compare receipts
|
||||
assert_eq!(receipt, receipt2);
|
||||
}
|
||||
|
||||
pub async fn test_all() {
|
||||
test_envelope_round_trip().await;
|
||||
test_receipt_round_trip().await;
|
||||
}
|
Reference in New Issue
Block a user