pub mod entry;
pub mod intern_archive_encryption;
pub mod single;
use crate::context::EnkryptitContext;
use crate::encryption::folder_encryption::entry::collect_entries_from_folder::collect_folder_entries;
use crate::encryption::folder_encryption::single::{decrypt_folder_single, encrypt_folder_single};
use crate::errors::EnkryptitError;
use crate::key::EnkryptitKey;
use crate::metadatas::{ArchiveHeader, FolderMetadata};
use crate::types::KeyType;
use crate::types::Mode;
use gradient_bar::GradientProgressBar;
use postcard::from_bytes;
use std::fs::File;
use std::io::{BufWriter, Seek, SeekFrom, Write};
pub fn encrypt_folder(
folder_path: &str,
context: &mut EnkryptitContext,
keytype: &KeyType,
) -> Result<String, EnkryptitError> {
let enkryptit_key = EnkryptitKey::resolve(Mode::Encrypting, keytype, context, folder_path)?;
let pb = GradientProgressBar::new_spinner("Treating folder...");
let mut entries = collect_folder_entries(folder_path, context)?;
if entries.is_empty() {
return Err(EnkryptitError::FileError);
}
let mut folder_meta = FolderMetadata::new(enkryptit_key.key_type_as_ref().clone());
for entry in &entries {
folder_meta.entries.push(entry.clone());
}
const HEADER_REGION_SIZE: usize = 64;
let archive_path = format!("{}.encky", folder_path);
{
let mut archive_file = BufWriter::new(File::create(&archive_path)?);
let placeholder_header = ArchiveHeader::new(true, 0);
let mut header_bytes = placeholder_header.pack()?;
header_bytes.resize(HEADER_REGION_SIZE, 0);
archive_file.write_all(&[HEADER_REGION_SIZE as u8])?;
archive_file.write_all(&header_bytes)?;
}
let data_start: u64 = 1 + HEADER_REGION_SIZE as u64;
pb.finish();
encrypt_folder_single(
folder_path,
enkryptit_key,
&mut entries,
data_start,
context,
&archive_path,
)?;
let pb = GradientProgressBar::new_spinner("Finishing folder treatment...");
folder_meta.entries.clear();
for entry in &entries {
folder_meta.entries.push(entry.clone());
}
let serialized_meta = folder_meta.pack()?;
let meta_len = serialized_meta.len() as u32;
{
let mut archive_file = BufWriter::new(File::options().append(true).open(&archive_path)?);
archive_file.write_all(&serialized_meta)?;
}
{
let final_header = ArchiveHeader::new(true, meta_len);
let mut final_header_bytes = final_header.pack()?;
final_header_bytes.resize(HEADER_REGION_SIZE, 0);
let mut archive_file = File::options().read(true).write(true).open(&archive_path)?;
archive_file.seek(SeekFrom::Start(1))?;
archive_file.write_all(&final_header_bytes)?;
}
pb.finish();
Ok(archive_path)
}
pub fn decrypt_folder(
archive_path: &str,
meta_bytes: &[u8],
payload_offset: u64,
version: u8,
context: &mut EnkryptitContext,
) -> Result<String, EnkryptitError> {
let metadatas: FolderMetadata = from_bytes(meta_bytes)?;
let entries = metadatas.entries;
let enkryptit_key =
EnkryptitKey::resolve(Mode::Decrypting, &metadatas.key_type, context, archive_path)?;
let dest_folder = archive_path.strip_suffix(".encky").unwrap_or(archive_path);
std::fs::create_dir_all(dest_folder)?;
decrypt_folder_single(
archive_path,
dest_folder,
&entries,
enkryptit_key,
payload_offset,
version,
context,
)?;
Ok(dest_folder.to_string())
}