serde_encrypt_core/encrypt/
encrypted_message.rs

1//! Encrypted message structure.
2
3use core::convert::TryInto;
4
5use alloc::vec::Vec;
6
7use crate::error::Error;
8
9/// 192-bit / 24-byte nonce used in XChaCha20 / XSalsa20
10const NONCE_SIZE: usize = 24;
11
12/// Encrypted message structure.
13///
14/// This struct is serialized into `Vec<u8>` (and deserialized from `Vec<u8>`).
15/// In order to send an EncryptedMessage to a remote receiver, use `let bin = encrypted_message.serialize();`.
16/// Then, the receiver should deserialize it by `let encrypted_message = EncryptedMessage::deserialize(bin);`.
17///
18/// This struct includes Nonce, which is internally used when a receiver decrypt the encrypted message.
19#[derive(Clone, Eq, PartialEq, Debug)]
20pub struct EncryptedMessage {
21    encrypted: Vec<u8>,
22
23    /// XChaCha20 nonce (192-bit / 24-byte)
24    nonce: [u8; NONCE_SIZE],
25}
26
27impl EncryptedMessage {
28    #[doc(hidden)]
29    pub fn new(encrypted: Vec<u8>, nonce: [u8; 24]) -> Self {
30        Self { encrypted, nonce }
31    }
32
33    /// Serialize this encrypted message into binary in order to send it to a remote receiver.
34    pub fn serialize(mut self) -> Vec<u8> {
35        let mut serialized: Vec<u8> = self.nonce.to_vec();
36        serialized.append(&mut self.encrypted);
37        serialized
38    }
39
40    /// Deserializer function for a receiver.
41    ///
42    /// # Failures
43    ///
44    /// - [DeserializationError](crate::error::ErrorKind::DeserializationError) when:
45    ///   - binary data does not have nonce.
46    pub fn deserialize(mut serialized_encrypted_message: Vec<u8>) -> Result<Self, Error> {
47        if serialized_encrypted_message.len() >= NONCE_SIZE {
48            let encrypted = serialized_encrypted_message.split_off(NONCE_SIZE);
49            Ok(Self {
50                encrypted,
51                nonce: serialized_encrypted_message
52                    .try_into()
53                    .expect("length already checked"),
54            })
55        } else {
56            Err(Error::decryption_error(
57                "binary data to decrypt (and then deserialize) does not seem to have nonce data",
58            ))
59        }
60    }
61
62    /// Ref to XChaCha20 nonce (192-bit / 24-byte) used to create this encrypted message.
63    pub fn nonce(&self) -> &[u8] {
64        &self.nonce
65    }
66
67    /// Ref to encrypted message.
68    pub fn encrypted(&self) -> &[u8] {
69        &self.encrypted
70    }
71
72    /// Payload size in bytes.
73    #[allow(clippy::len_without_is_empty)]
74    pub fn len(&self) -> usize {
75        self.encrypted().len() + self.nonce().len()
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use alloc::vec;
82
83    use crate::error::ErrorKind;
84
85    use super::*;
86
87    #[test]
88    fn test_serialization() -> Result<(), Error> {
89        let encrypted_message = EncryptedMessage::new(b"*ENCRYPTED*".to_vec(), [42u8; 24]);
90        let bin = encrypted_message.clone().serialize();
91        assert_eq!(EncryptedMessage::deserialize(bin)?, encrypted_message);
92        Ok(())
93    }
94
95    #[test]
96    fn test_decryption_error_on_no_nonce() {
97        let bin = vec![42u8; NONCE_SIZE - 1];
98        let e = EncryptedMessage::deserialize(bin).unwrap_err();
99        assert_eq!(e.kind(), &ErrorKind::DecryptionError);
100    }
101}