Skip to main content

shadow_crypt_core/v1/
file.rs

1use crate::{
2    errors::{FileError, HeaderError},
3    file::PlaintextFile,
4    memory::SecureKey,
5};
6
7use super::header::FileHeader;
8
9/// Represents a complete encrypted file with header and content
10#[derive(Debug)]
11pub struct EncryptedFile {
12    header: FileHeader,
13    ciphertext: Vec<u8>,
14}
15
16impl EncryptedFile {
17    pub fn new(header: FileHeader, ciphertext: Vec<u8>) -> Self {
18        Self { header, ciphertext }
19    }
20
21    /// Parses a serialized v1 file into its header and content ciphertext.
22    pub fn from_bytes(bytes: &[u8]) -> Result<Self, HeaderError> {
23        let header = FileHeader::try_deserialize(bytes)?;
24        let ciphertext = bytes[header.header_length()..].to_vec();
25
26        Ok(Self::new(header, ciphertext))
27    }
28
29    /// Serializes the complete file (header followed by content ciphertext).
30    pub fn to_bytes(&self) -> Vec<u8> {
31        let mut bytes = self.header.serialize();
32        bytes.extend_from_slice(&self.ciphertext);
33        bytes
34    }
35
36    /// Decrypts the filename and content. v1 has no header authentication,
37    /// so only the AEAD tags of the two ciphertexts are verified.
38    pub fn decrypt(&self, key: &SecureKey) -> Result<PlaintextFile, FileError> {
39        let filename = self.header.decrypt_filename(key)?;
40        let content = self.header.decrypt_content(&self.ciphertext, key)?;
41
42        Ok(PlaintextFile::new(filename, content))
43    }
44
45    pub fn header(&self) -> &FileHeader {
46        &self.header
47    }
48    pub fn ciphertext(&self) -> &[u8] {
49        &self.ciphertext
50    }
51}