use super::*;
async fn test_envelope_round_trip(
envelope_version: EnvelopeVersion,
vcrypto: &AsyncCryptoSystemGuard<'_>,
network_key: Option<BareSharedSecret>,
) {
let crypto = vcrypto.crypto();
if network_key.is_some() {
info!(
"--- test envelope round trip {} w/network key ---",
vcrypto.kind()
);
} else {
info!("--- test envelope round trip {} ---", vcrypto.kind());
}
let ts = Timestamp::from(0x12345678ABCDEF69u64);
let nonce = vcrypto.random_nonce().await;
let (sender_public_key, sender_secret) = vcrypto.generate_keypair().await.into_split();
let sender_id = crypto
.routing_table()
.generate_node_id(&sender_public_key)
.expect("should generate node id");
let (recipient_public_key, recipient_secret) = vcrypto.generate_keypair().await.into_split();
let recipient_id = crypto
.routing_table()
.generate_node_id(&recipient_public_key)
.expect("should generate node id");
let envelope = match envelope_version {
ENVELOPE_VERSION_ENV0 => {
Envelope::try_new_env0(&crypto, vcrypto.kind(), ts, nonce, sender_id, recipient_id)
.expect("should create envelope")
}
_ => {
panic!("unsupported envelope version");
}
};
let body = Bytes::copy_from_slice(b"This is an arbitrary body");
let enc_data = envelope
.to_encrypted_data(&crypto, body.clone(), &sender_secret, &network_key)
.await
.expect("failed to encrypt data");
let envelope2 = Envelope::try_from_signed_data(&crypto, enc_data.clone(), &network_key)
.await
.expect("failed to deserialize envelope from data");
let body2 = envelope2
.decrypt_body(&crypto, enc_data.clone(), &recipient_secret, &network_key)
.await
.expect("failed to decrypt envelope body");
assert_eq!(envelope, envelope2);
assert_eq!(body.to_vec(), body2);
let enc_data_len = enc_data.len();
let mut mod_enc_data: BytesMut = enc_data.clone().into();
mod_enc_data[enc_data_len - 1] ^= 0x80u8;
let mod_enc_data = mod_enc_data.freeze();
assert!(
Envelope::try_from_signed_data(&crypto, mod_enc_data, &network_key)
.await
.is_err(),
"should have failed to decode envelope with modified signature"
);
let mut mod_enc_data2: BytesMut = enc_data.clone().into();
mod_enc_data2[enc_data_len - 65] ^= 0x80u8;
let mod_enc_data2 = mod_enc_data2.freeze();
assert!(
Envelope::try_from_signed_data(&crypto, mod_enc_data2, &network_key)
.await
.is_err(),
"should have failed to decode envelope with modified data"
);
}
async fn test_receipt_round_trip(
receipt_version: ReceiptVersion,
vcrypto: &AsyncCryptoSystemGuard<'_>,
) {
let crypto = vcrypto.crypto();
info!("--- test receipt round trip ---");
let body = Bytes::copy_from_slice(b"This is an arbitrary body");
let nonce = vcrypto.random_nonce().await;
let (sender_public_key, sender_secret) = vcrypto.generate_keypair().await.into_split();
let sender_id = crypto
.routing_table()
.generate_node_id(&sender_public_key)
.expect("should generate node id");
let receipt = match receipt_version {
RECEIPT_VERSION_RCP0 => {
Receipt::try_new_rcp0(&crypto, vcrypto.kind(), nonce, sender_id, body)
.expect("should not fail")
}
_ => {
panic!("unsupported receipt version");
}
};
let enc_data = receipt
.to_signed_data(&crypto, &sender_secret)
.await
.expect("failed to make signed data");
let receipt2 = Receipt::try_from_signed_data(&crypto, enc_data.clone())
.await
.expect("failed to deserialize envelope from data");
let mut mod_enc_data: BytesMut = enc_data.clone().into();
mod_enc_data[5] = 0x01;
let mod_enc_data = mod_enc_data.freeze();
let _ = Receipt::try_from_signed_data(&crypto, mod_enc_data)
.await
.expect_err("should have failed to decrypt using wrong secret");
assert_eq!(receipt, receipt2);
}
pub async fn test_all() {
let api = crypto_tests_startup().await;
let crypto = api.crypto().unwrap();
for ev in VALID_ENVELOPE_VERSIONS {
for v in VALID_CRYPTO_KINDS {
let vcrypto = crypto.get_async(v).unwrap();
test_envelope_round_trip(ev, &vcrypto, None).await;
test_envelope_round_trip(
ev,
&vcrypto,
Some(vcrypto.random_shared_secret().await.into_value()),
)
.await;
}
}
for rv in VALID_RECEIPT_VERSIONS {
for v in VALID_CRYPTO_KINDS {
let vcrypto = crypto.get_async(v).unwrap();
test_receipt_round_trip(rv, &vcrypto).await;
}
}
crypto_tests_shutdown(api.clone()).await;
assert!(api.is_shutdown());
}