use core::convert::TryInto;
use alloc::vec::Vec;
use crate::error::Error;
const NONCE_SIZE: usize = 24;
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct EncryptedMessage {
encrypted: Vec<u8>,
nonce: [u8; NONCE_SIZE],
}
impl EncryptedMessage {
#[doc(hidden)]
pub fn new(encrypted: Vec<u8>, nonce: [u8; 24]) -> Self {
Self { encrypted, nonce }
}
pub fn serialize(mut self) -> Vec<u8> {
let mut serialized: Vec<u8> = self.nonce.to_vec();
serialized.append(&mut self.encrypted);
serialized
}
pub fn deserialize(mut serialized_encrypted_message: Vec<u8>) -> Result<Self, Error> {
if serialized_encrypted_message.len() >= NONCE_SIZE {
let encrypted = serialized_encrypted_message.split_off(NONCE_SIZE);
Ok(Self {
encrypted,
nonce: serialized_encrypted_message
.try_into()
.expect("length already checked"),
})
} else {
Err(Error::decryption_error(
"binary data to decrypt (and then deserialize) does not seem to have nonce data",
))
}
}
pub fn nonce(&self) -> &[u8] {
&self.nonce
}
pub fn encrypted(&self) -> &[u8] {
&self.encrypted
}
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> usize {
self.encrypted().len() + self.nonce().len()
}
}
#[cfg(test)]
mod tests {
use alloc::vec;
use crate::error::ErrorKind;
use super::*;
#[test]
fn test_serialization() -> Result<(), Error> {
let encrypted_message = EncryptedMessage::new(b"*ENCRYPTED*".to_vec(), [42u8; 24]);
let bin = encrypted_message.clone().serialize();
assert_eq!(EncryptedMessage::deserialize(bin)?, encrypted_message);
Ok(())
}
#[test]
fn test_decryption_error_on_no_nonce() {
let bin = vec![42u8; NONCE_SIZE - 1];
let e = EncryptedMessage::deserialize(bin).unwrap_err();
assert_eq!(e.kind(), &ErrorKind::DecryptionError);
}
}