Skip to content
This repository was archived by the owner on Jun 23, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions encryptx-backend/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use rand::RngCore;
use std::fs;
use std::io;
use std::path::Path;
use zstd::stream::{encode_all, decode_all};

/// Command-line interface for EncryptX Backend.
///
Expand Down Expand Up @@ -244,15 +245,19 @@ pub async fn run_cli() -> Result<bool, CliError> {

println!("🔐 Encrypting file '{file}'...");

// Perform encryption
// Compress before encryption
let compressed = encode_all(&data[..], 3).map_err(|e| CliError::Crypto(format!("Compression error: {e}")))?;
let mut compressed_with_flag = Vec::with_capacity(1 + compressed.len());
compressed_with_flag.push(0x01);
compressed_with_flag.extend_from_slice(&compressed);
let encrypted = if let Some(password) = password {
// Password-based encryption (Argon2id)
let mut salt = [0u8; 32];
rand::rngs::OsRng
.try_fill_bytes(&mut salt)
.map_err(|e| CliError::Crypto(format!("Failed to generate salt: {e}")))?;

crypto::encrypt_with_password_async(&data, password, orig_name, salt.to_vec())
crypto::encrypt_with_password_async(&compressed_with_flag, password, orig_name, salt.to_vec())
.await
.map_err(|e| CliError::Crypto(format!("Password encryption failed: {e}")))?
} else {
Expand All @@ -276,7 +281,7 @@ pub async fn run_cli() -> Result<bool, CliError> {
k.to_vec()
};

crypto::encrypt_with_header(&data, &final_key, orig_name)
crypto::encrypt_with_header(&compressed_with_flag, &final_key, orig_name)
.map_err(|e| CliError::Crypto(format!("Key encryption failed: {e}")))?
};

Expand Down Expand Up @@ -357,15 +362,21 @@ pub async fn run_cli() -> Result<bool, CliError> {
check_output_file(&output_file, force)?;

// Write decrypted file
fs::write(&output_file, &decrypted).map_err(|e| {
// Decompress after decryption if needed
let output_bytes = if decrypted.first() == Some(&0x01) {
decode_all(&decrypted[1..]).map_err(|e| CliError::Crypto(format!("Decompression error: {e}")))?
} else {
decrypted
};
fs::write(&output_file, &output_bytes).map_err(|e| {
CliError::Io(io::Error::new(
e.kind(),
format!("Failed to write decrypted file '{output_file}': {e}"),
))
})?;

println!("✅ Decrypted file written to '{output_file}'");
println!("📊 Decrypted size: {} bytes", decrypted.len());
println!("📊 Decrypted size: {} bytes", output_bytes.len());

Ok(true)
}
Expand Down
4 changes: 4 additions & 0 deletions encryptx-backend/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ fn generate_secure_key() -> [u8; 32] {
/// An encrypted file as a binary stream with appropriate headers, or an error response if encryption fails or headers are invalid.
async fn encrypt_file(req: HttpRequest, body: Bytes) -> impl Responder {
// Compress the file bytes before encryption
let original_size = body.len();
let compressed = match encode_all(&body[..], 3) {
Ok(c) => c,
Err(e) => {
Expand All @@ -103,6 +104,9 @@ async fn encrypt_file(req: HttpRequest, body: Bytes) -> impl Responder {
let mut compressed_with_flag = Vec::with_capacity(1 + compressed.len());
compressed_with_flag.push(0x01);
compressed_with_flag.extend_from_slice(&compressed);
let compressed_size = compressed_with_flag.len();
println!("Original size: {original_size} bytes");
println!("Compressed size: {compressed_size} bytes");

// Check for password-based encryption request
if let Some(password_header) = req.headers().get("x-password") {
Expand Down