Switch to Ed25519 signature + XChaCha20
also add infoq nodeinfo
This commit is contained in:
		
							
								
								
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -4186,6 +4186,7 @@ dependencies = [
 | 
			
		||||
 "capnp",
 | 
			
		||||
 "capnpc",
 | 
			
		||||
 "cfg-if 1.0.0",
 | 
			
		||||
 "chacha20",
 | 
			
		||||
 "chacha20poly1305",
 | 
			
		||||
 "chrono",
 | 
			
		||||
 "config 0.12.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@ hex = "^0"
 | 
			
		||||
generic-array = "^0"
 | 
			
		||||
secrecy = "^0"
 | 
			
		||||
chacha20poly1305 = "^0"
 | 
			
		||||
chacha20 = "^0"
 | 
			
		||||
hashlink = { path = "../external/hashlink", features = ["serde_impl"] }
 | 
			
		||||
serde-big-array = "^0"
 | 
			
		||||
futures-util = { version = "^0", default_features = false, features = ["alloc"] }
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,8 @@ use super::key::*;
 | 
			
		||||
use crate::intf::*;
 | 
			
		||||
use crate::xx::*;
 | 
			
		||||
use crate::*;
 | 
			
		||||
use chacha20::cipher::{NewCipher, StreamCipher};
 | 
			
		||||
use chacha20::XChaCha20;
 | 
			
		||||
use chacha20poly1305 as ch;
 | 
			
		||||
use chacha20poly1305::aead::{AeadInPlace, NewAead};
 | 
			
		||||
use core::convert::TryInto;
 | 
			
		||||
@@ -16,7 +18,7 @@ pub type SharedSecret = [u8; 32];
 | 
			
		||||
pub type Nonce = [u8; 24];
 | 
			
		||||
 | 
			
		||||
const DH_CACHE_SIZE: usize = 1024;
 | 
			
		||||
pub const ENCRYPTION_OVERHEAD: usize = 16;
 | 
			
		||||
pub const AEAD_OVERHEAD: usize = 16;
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Hash)]
 | 
			
		||||
struct DHCacheKey {
 | 
			
		||||
@@ -222,7 +224,7 @@ impl Crypto {
 | 
			
		||||
        s
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn decrypt_in_place(
 | 
			
		||||
    pub fn decrypt_in_place_aead(
 | 
			
		||||
        body: &mut Vec<u8>,
 | 
			
		||||
        nonce: &Nonce,
 | 
			
		||||
        shared_secret: &SharedSecret,
 | 
			
		||||
@@ -236,20 +238,20 @@ impl Crypto {
 | 
			
		||||
            .map_err(logthru_crypto!())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn decrypt(
 | 
			
		||||
    pub fn decrypt_aead(
 | 
			
		||||
        body: &[u8],
 | 
			
		||||
        nonce: &Nonce,
 | 
			
		||||
        shared_secret: &SharedSecret,
 | 
			
		||||
        associated_data: Option<&[u8]>,
 | 
			
		||||
    ) -> Result<Vec<u8>, String> {
 | 
			
		||||
        let mut out = body.to_vec();
 | 
			
		||||
        Self::decrypt_in_place(&mut out, nonce, shared_secret, associated_data)
 | 
			
		||||
        Self::decrypt_in_place_aead(&mut out, nonce, shared_secret, associated_data)
 | 
			
		||||
            .map_err(map_to_string)
 | 
			
		||||
            .map_err(logthru_crypto!())?;
 | 
			
		||||
        Ok(out)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn encrypt_in_place(
 | 
			
		||||
    pub fn encrypt_in_place_aead(
 | 
			
		||||
        body: &mut Vec<u8>,
 | 
			
		||||
        nonce: &Nonce,
 | 
			
		||||
        shared_secret: &SharedSecret,
 | 
			
		||||
@@ -264,16 +266,27 @@ impl Crypto {
 | 
			
		||||
            .map_err(logthru_crypto!())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn encrypt(
 | 
			
		||||
    pub fn encrypt_aead(
 | 
			
		||||
        body: &[u8],
 | 
			
		||||
        nonce: &Nonce,
 | 
			
		||||
        shared_secret: &SharedSecret,
 | 
			
		||||
        associated_data: Option<&[u8]>,
 | 
			
		||||
    ) -> Result<Vec<u8>, String> {
 | 
			
		||||
        let mut out = body.to_vec();
 | 
			
		||||
        Self::encrypt_in_place(&mut out, nonce, shared_secret, associated_data)
 | 
			
		||||
        Self::encrypt_in_place_aead(&mut out, nonce, shared_secret, associated_data)
 | 
			
		||||
            .map_err(map_to_string)
 | 
			
		||||
            .map_err(logthru_crypto!())?;
 | 
			
		||||
        Ok(out)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn crypt_in_place_no_auth(body: &mut Vec<u8>, nonce: &Nonce, shared_secret: &SharedSecret) {
 | 
			
		||||
        let mut cipher = XChaCha20::new(shared_secret.into(), nonce.into());
 | 
			
		||||
        cipher.apply_keystream(body);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn crypt_no_auth(body: &[u8], nonce: &Nonce, shared_secret: &SharedSecret) -> Vec<u8> {
 | 
			
		||||
        let mut out = body.to_vec();
 | 
			
		||||
        Self::crypt_in_place_no_auth(&mut out, nonce, shared_secret);
 | 
			
		||||
        out
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,14 +29,13 @@ use core::convert::TryInto;
 | 
			
		||||
//     sender_id: [u8; 32],         // 0x2A: Node ID of the message source, which is the Ed25519 public key of the sender (must be verified with find_node if this is a new node_id/address combination)
 | 
			
		||||
//     recipient_id: [u8; 32],      // 0x4A: Node ID of the intended recipient, which is the Ed25519 public key of the recipient (must be the receiving node, or a relay lease holder)
 | 
			
		||||
//                                  // 0x6A: message is appended (operations)
 | 
			
		||||
//                                  //       encrypted by XChaCha20Poly1305(nonce,x25519(recipient_id, sender_secret_key))
 | 
			
		||||
//                                  //       decryptable by XChaCha20Poly1305(nonce,x25519(sender_id, recipient_secret_key))
 | 
			
		||||
//                                  //       entire header needs to be included in message digest, relays are not allowed to modify the envelope without invalidating the signature.
 | 
			
		||||
//                                  // encrypted by XChaCha20Poly1305(nonce,x25519(recipient_id, sender_secret_key))
 | 
			
		||||
//     signature: [u8; 64],         // 0x?? (end-0x40): Ed25519 signature of the entire envelope including header is appended to the packet
 | 
			
		||||
//                                  // entire header needs to be included in message digest, relays are not allowed to modify the envelope without invalidating the signature.
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
pub const MAX_ENVELOPE_SIZE: usize = 65507;
 | 
			
		||||
pub const MIN_ENVELOPE_SIZE: usize = 106;
 | 
			
		||||
pub const AEAD_ADDITIONAL_SIZE: usize = 16;
 | 
			
		||||
pub const MIN_ENVELOPE_SIZE: usize = 0x6A + 0x40; // Header + Signature
 | 
			
		||||
pub const ENVELOPE_MAGIC: &[u8; 4] = b"VLID";
 | 
			
		||||
pub const MIN_VERSION: u8 = 0u8;
 | 
			
		||||
pub const MAX_VERSION: u8 = 0u8;
 | 
			
		||||
@@ -77,7 +76,7 @@ impl Envelope {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn from_data(data: &[u8]) -> Result<Envelope, ()> {
 | 
			
		||||
    pub fn from_signed_data(data: &[u8]) -> Result<Envelope, ()> {
 | 
			
		||||
        // Ensure we are at least the length of the envelope
 | 
			
		||||
        if data.len() < MIN_ENVELOPE_SIZE {
 | 
			
		||||
            trace!("envelope too small: len={}", data.len());
 | 
			
		||||
@@ -155,6 +154,12 @@ impl Envelope {
 | 
			
		||||
            return Err(());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Get signature
 | 
			
		||||
        let signature = DHTSignature::new(data[(data.len() - 64)..].try_into().map_err(drop)?);
 | 
			
		||||
 | 
			
		||||
        // Validate signature
 | 
			
		||||
        verify(&sender_id, &data[0..(data.len() - 64)], &signature).map_err(drop)?;
 | 
			
		||||
 | 
			
		||||
        // Return envelope
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            version,
 | 
			
		||||
@@ -176,13 +181,8 @@ impl Envelope {
 | 
			
		||||
        // Get DH secret
 | 
			
		||||
        let dh_secret = crypto.cached_dh(&self.sender_id, node_id_secret)?;
 | 
			
		||||
 | 
			
		||||
        // Decrypt message and authenticate, including the envelope header as associated data to authenticate
 | 
			
		||||
        let body = Crypto::decrypt(
 | 
			
		||||
            &data[0x6A..],
 | 
			
		||||
            &self.nonce,
 | 
			
		||||
            &dh_secret,
 | 
			
		||||
            Some(&data[0..MIN_ENVELOPE_SIZE]),
 | 
			
		||||
        )?;
 | 
			
		||||
        // Decrypt message without authentication
 | 
			
		||||
        let body = Crypto::crypt_no_auth(&data[0x6A..data.len() - 64], &self.nonce, &dh_secret);
 | 
			
		||||
 | 
			
		||||
        Ok(body)
 | 
			
		||||
    }
 | 
			
		||||
@@ -203,7 +203,7 @@ impl Envelope {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Ensure body isn't too long
 | 
			
		||||
        let envelope_size: usize = body.len() + MIN_ENVELOPE_SIZE + AEAD_ADDITIONAL_SIZE;
 | 
			
		||||
        let envelope_size: usize = body.len() + MIN_ENVELOPE_SIZE;
 | 
			
		||||
        if envelope_size > MAX_ENVELOPE_SIZE {
 | 
			
		||||
            return Err(());
 | 
			
		||||
        }
 | 
			
		||||
@@ -234,11 +234,23 @@ impl Envelope {
 | 
			
		||||
            .map_err(drop)?;
 | 
			
		||||
 | 
			
		||||
        // Encrypt and authenticate message
 | 
			
		||||
        let encrypted_body =
 | 
			
		||||
            Crypto::encrypt(body, &self.nonce, &dh_secret, Some(&data[0..0x6A])).map_err(drop)?;
 | 
			
		||||
        let encrypted_body = Crypto::crypt_no_auth(body, &self.nonce, &dh_secret);
 | 
			
		||||
 | 
			
		||||
        // Write body
 | 
			
		||||
        data[0x6A..].copy_from_slice(encrypted_body.as_slice());
 | 
			
		||||
        if !encrypted_body.is_empty() {
 | 
			
		||||
            data[0x6A..envelope_size - 64].copy_from_slice(encrypted_body.as_slice());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Sign the envelope
 | 
			
		||||
        let signature = sign(
 | 
			
		||||
            &self.sender_id,
 | 
			
		||||
            node_id_secret,
 | 
			
		||||
            &data[0..(envelope_size - 64)],
 | 
			
		||||
        )
 | 
			
		||||
        .map_err(drop)?;
 | 
			
		||||
 | 
			
		||||
        // Append the signature
 | 
			
		||||
        data[(envelope_size - 64)..].copy_from_slice(&signature.bytes);
 | 
			
		||||
 | 
			
		||||
        Ok(data)
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -541,7 +541,7 @@ impl NetworkManager {
 | 
			
		||||
 | 
			
		||||
        // Decode envelope header (may fail signature validation)
 | 
			
		||||
        let envelope =
 | 
			
		||||
            Envelope::from_data(data).map_err(|_| "envelope failed to decode".to_owned())?;
 | 
			
		||||
            Envelope::from_signed_data(data).map_err(|_| "envelope failed to decode".to_owned())?;
 | 
			
		||||
 | 
			
		||||
        // Get routing table and rpc processor
 | 
			
		||||
        let (routing_table, rpc) = {
 | 
			
		||||
 
 | 
			
		||||
@@ -93,7 +93,7 @@ impl RPCProcessor {
 | 
			
		||||
                        )
 | 
			
		||||
                        .map_err(map_error_internal!("dh failed"))?;
 | 
			
		||||
                    let enc_msg_data =
 | 
			
		||||
                        Crypto::encrypt(blob_data.as_slice(), &nonce, &dh_secret, None)
 | 
			
		||||
                        Crypto::encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None)
 | 
			
		||||
                            .map_err(map_error_internal!("encryption failed"))?;
 | 
			
		||||
 | 
			
		||||
                    rhd_builder.set_blob(enc_msg_data.as_slice());
 | 
			
		||||
@@ -118,7 +118,7 @@ impl RPCProcessor {
 | 
			
		||||
                    &safety_route.secret_key,
 | 
			
		||||
                )
 | 
			
		||||
                .map_err(map_error_internal!("dh failed"))?;
 | 
			
		||||
            let enc_msg_data = Crypto::encrypt(blob_data.as_slice(), &nonce, &dh_secret, None)
 | 
			
		||||
            let enc_msg_data = Crypto::encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None)
 | 
			
		||||
                .map_err(map_error_internal!("encryption failed"))?;
 | 
			
		||||
 | 
			
		||||
            first_rhd_builder.set_blob(enc_msg_data.as_slice());
 | 
			
		||||
@@ -148,7 +148,7 @@ impl RPCProcessor {
 | 
			
		||||
            .crypto
 | 
			
		||||
            .cached_dh(&pr_pk, &sr.secret_key)
 | 
			
		||||
            .map_err(map_error_internal!("dh failed"))?;
 | 
			
		||||
        let enc_msg_data = Crypto::encrypt(&message_data, &nonce, &dh_secret, None)
 | 
			
		||||
        let enc_msg_data = Crypto::encrypt_aead(&message_data, &nonce, &dh_secret, None)
 | 
			
		||||
            .map_err(map_error_internal!("encryption failed"))?;
 | 
			
		||||
 | 
			
		||||
        // Prepare route operation
 | 
			
		||||
 
 | 
			
		||||
@@ -21,8 +21,8 @@ async fn shutdown(api: VeilidAPI) {
 | 
			
		||||
    trace!("test_table_store: finished");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub async fn test_enc_dec() {
 | 
			
		||||
    trace!("test_enc_dec");
 | 
			
		||||
pub async fn test_aead() {
 | 
			
		||||
    trace!("test_aead");
 | 
			
		||||
 | 
			
		||||
    let n1 = Crypto::get_random_nonce();
 | 
			
		||||
    let n2 = loop {
 | 
			
		||||
@@ -44,52 +44,101 @@ pub async fn test_enc_dec() {
 | 
			
		||||
    let body2 = body.clone();
 | 
			
		||||
    let size_before_encrypt = body.len();
 | 
			
		||||
    assert!(
 | 
			
		||||
        Crypto::encrypt_in_place(&mut body, &n1, &ss1, None).is_ok(),
 | 
			
		||||
        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 == ENCRYPTION_OVERHEAD,
 | 
			
		||||
        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(&mut body, &n1, &ss1, None).is_ok(),
 | 
			
		||||
        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(&mut body3, &n2, &ss1, None).is_err(),
 | 
			
		||||
        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(&mut body4, &n1, &ss2, None).is_err(),
 | 
			
		||||
        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(&mut body5, &n1, &ss2, Some(b"foobar")).is_err(),
 | 
			
		||||
        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(LOREM_IPSUM, &n1, &ss1, None).is_err(),
 | 
			
		||||
        Crypto::decrypt_aead(LOREM_IPSUM, &n1, &ss1, None).is_err(),
 | 
			
		||||
        "should fail authentication"
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let body5 = Crypto::encrypt(LOREM_IPSUM, &n1, &ss1, None).unwrap();
 | 
			
		||||
    let body6 = Crypto::decrypt(&body5, &n1, &ss1, None).unwrap();
 | 
			
		||||
    let body7 = Crypto::encrypt(LOREM_IPSUM, &n1, &ss1, None).unwrap();
 | 
			
		||||
    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();
 | 
			
		||||
@@ -119,7 +168,8 @@ pub async fn test_dh(crypto: Crypto) {
 | 
			
		||||
pub async fn test_all() {
 | 
			
		||||
    let api = startup().await;
 | 
			
		||||
    let crypto = api.crypto().unwrap();
 | 
			
		||||
    test_enc_dec().await;
 | 
			
		||||
    test_aead().await;
 | 
			
		||||
    test_no_auth().await;
 | 
			
		||||
    test_dh(crypto).await;
 | 
			
		||||
    shutdown(api.clone()).await;
 | 
			
		||||
    assert!(api.is_shutdown());
 | 
			
		||||
 
 | 
			
		||||
@@ -33,19 +33,31 @@ pub async fn test_envelope_round_trip() {
 | 
			
		||||
 | 
			
		||||
    // Deserialize from bytes
 | 
			
		||||
    let envelope2 =
 | 
			
		||||
        Envelope::from_data(&enc_data).expect("failed to deserialize envelope from data");
 | 
			
		||||
        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");
 | 
			
		||||
 | 
			
		||||
    envelope2
 | 
			
		||||
        .decrypt_body(crypto.clone(), &enc_data, &sender_secret)
 | 
			
		||||
        .expect_err("should have failed to decrypt using wrong secret");
 | 
			
		||||
 | 
			
		||||
    // 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user