refactor network manager

This commit is contained in:
John Smith
2022-05-31 19:54:52 -04:00
parent ad4b6328ac
commit 8148c37708
51 changed files with 500 additions and 389 deletions

View File

@@ -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::*;

View File

@@ -0,0 +1,5 @@
pub mod test_crypto;
pub mod test_dht_key;
pub mod test_envelope_receipt;
use super::*;

View 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());
}

View 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;
}

View 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;
}