Skip to content

Commit

Permalink
Finished linking up all algos
Browse files Browse the repository at this point in the history
  • Loading branch information
ThaddeusTreloar committed Oct 10, 2023
1 parent f5c57dc commit b6b7dc4
Show file tree
Hide file tree
Showing 9 changed files with 437 additions and 413 deletions.
6 changes: 4 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,17 @@ To install Zap, run the following command from the project root:

Where the `[OUTPUT]` is the path to which you want to store the `.zap` file.

- The zap file can optionally be encrypted with by providing the `-e` flag and choosing `password` or `key`. Note that `key` method is not supported yet.
Using `zap archive --help` will list the available options for encryption and compression.

### In order to **decompress** a Zap archive

`zap extract [ARCHIVE] [OUTPUT]`

Where the `[ARCHIVE]` is the path to the file which you want to extract and the `[OUTPUT]` is the folder in which you want the contents to be placed inside.

- If the Zap file was encrypted, the `-e` flag needs to be provided along with the correct encryption method. *This will hopefully be resolved in future versions*
Using `zap archive --help` will list the available options for encryption and compression.

Unfortunately, in it's current state, that compression and encryption methods aren't stored in metadata and must be given when extracting. this will be fixed in coming releases.

### In order to **list** the contents of a Zap archive

Expand Down
75 changes: 75 additions & 0 deletions src/bin/cli_util/compression.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use clap::ValueEnum;
use zap::compression::CompressionType;



#[derive(Debug, Clone, ValueEnum)]
pub enum CompressionLevel{
Fastest,
Best,
Default,
}

impl From<String> for CompressionLevel {
fn from(s: String) -> Self {
match s.as_str() {
"fastest" => CompressionLevel::Fastest,
"best" => CompressionLevel::Best,
_ => CompressionLevel::Default,
}
}
}

impl Into<flate2::Compression> for CompressionLevel {
fn into(self) -> flate2::Compression {
match self {
CompressionLevel::Fastest => flate2::Compression::fast(),
CompressionLevel::Best => flate2::Compression::best(),
CompressionLevel::Default => flate2::Compression::default(),
}
}
}

#[derive(Default, Debug, Clone, ValueEnum)]
pub enum BinCompressionType {
Passthrough,
#[default]
Lz4,
Gzip,
Snappy,
}

impl From<String> for BinCompressionType {
fn from(s: String) -> Self {
match s.as_str() {
"passthrough" => Self::Passthrough,
"lz4" => Self::Lz4,
"gzip" => Self::Gzip,
"snappy" => Self::Snappy,
"" => Self::default(),
_ => Self::Passthrough,
}
}
}

impl From<CompressionType> for BinCompressionType {
fn from(e: CompressionType) -> Self {
match e {
CompressionType::Passthrough => Self::Passthrough,
CompressionType::Lz4 => Self::Lz4,
CompressionType::Gzip => Self::Gzip,
CompressionType::Snappy => Self::Snappy,
}
}
}

impl Into<CompressionType> for BinCompressionType {
fn into(self) -> CompressionType {
match self {
BinCompressionType::Passthrough => CompressionType::Passthrough,
BinCompressionType::Lz4 => CompressionType::Lz4,
BinCompressionType::Gzip => CompressionType::Gzip,
BinCompressionType::Snappy => CompressionType::Snappy,
}
}
}
47 changes: 43 additions & 4 deletions src/bin/cli_util/encryption.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,47 @@
use clap::ValueEnum;
use zap::encryption::EncryptionType;

// Consider moving
#[derive(Debug, Clone, ValueEnum)]
pub enum SecretType {
Password,
Key
#[derive(Debug, Default, Clone, ValueEnum)]
pub enum BinEncryptionType {
Passthrough,
#[default]
XChaCha,
AesGcm,
ChaCha,
}

impl From<String> for BinEncryptionType {
fn from(s: String) -> Self {
match s.as_str() {
"passthrough" => Self::Passthrough,
"xchacha" => Self::XChaCha,
"aesgcm" => Self::AesGcm,
"chacha" => Self::ChaCha,
"" => Self::default(),
_ => Self::Passthrough,
}
}
}

impl From<EncryptionType> for BinEncryptionType {
fn from(e: EncryptionType) -> Self {
match e {
EncryptionType::Passthrough => Self::Passthrough,
EncryptionType::XChaCha => Self::XChaCha,
EncryptionType::AesGcm => Self::AesGcm,
EncryptionType::ChaCha => Self::ChaCha,
}
}
}

impl Into<EncryptionType> for BinEncryptionType {
fn into(self) -> EncryptionType {
match self {
BinEncryptionType::Passthrough => EncryptionType::Passthrough,
BinEncryptionType::XChaCha => EncryptionType::XChaCha,
BinEncryptionType::AesGcm => EncryptionType::AesGcm,
BinEncryptionType::ChaCha => EncryptionType::ChaCha,
}
}
}
144 changes: 80 additions & 64 deletions src/bin/cli_util/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod compression;
mod encryption;
mod logging;
mod password;
Expand All @@ -10,19 +11,18 @@ use std::{
use clap::{Parser, Subcommand};

use log::info;
use zap::{
encryption::EncryptionSecret,
error::{EncryptionKeyError, EncryptionSecretError, ZapError},
};
use zap::{encryption::EncryptionSecret, error::ZapError};

use zapf::{pack_files, unpack_files};

use crate::cli_util::{
logging::init_logger,
password::{get_password_confirm, get_password_noconf},
};
use crate::cli_util::{logging::init_logger, password::get_password_confirm};

use self::{encryption::SecretType, logging::Verbosity};
use self::{
compression::{BinCompressionType, CompressionLevel},
encryption::BinEncryptionType,
logging::Verbosity,
password::get_password_noconf,
};

#[derive(Debug, Parser)]
#[command(
Expand All @@ -49,31 +49,32 @@ enum Command {
input: String,
/// Output file
output: String,

/// Whether to encrypt the data
#[arg(short, long)]
encryption: Option<SecretType>,
/// If SecretType is key then keypath must be provided
#[arg(short, long)]
keypath: Option<String>,
#[arg(short, long, default_value = "normal")]
verbosity: Verbosity,
#[arg(long, short, default_value = "passthrough")]
encryption_algorithm: BinEncryptionType,
#[arg(long, short, default_value = "passthrough")]
compression_algorithm: BinCompressionType,
#[arg(long, default_value = "fastest")]
compression_level: CompressionLevel,
},
Extract {
/// Input file
input: String,

/// Output folder
output: String,

/// Whether to encrypt the data
#[arg(short, long)]
encryption: Option<SecretType>,
/// If SecretType is key then keypath must be provided
#[arg(short, long)]
keypath: Option<String>,
#[arg(short, long, default_value = "normal")]
verbosity: Verbosity,
#[arg(long, short, default_value = "passthrough")]
encryption_algorithm: BinEncryptionType,
#[arg(long, short, default_value = "passthrough")]
compression_algorithm: BinCompressionType,
},
List {
archive: String,
Expand All @@ -88,52 +89,71 @@ impl Command {
Command::Archive {
input,
output,
encryption,
keypath,
verbosity,
} => Self::archive(input, output, encryption, keypath, verbosity),
encryption_algorithm,
compression_algorithm,
compression_level,
} => Self::archive(
input,
output,
keypath,
verbosity,
encryption_algorithm,
compression_algorithm,
compression_level,
),
Command::Extract {
input,
output,
encryption,
keypath,
verbosity,
} => Self::extract(input, output, encryption, keypath, verbosity),
encryption_algorithm,
compression_algorithm,
} => Self::extract(
input,
output,
keypath,
verbosity,
encryption_algorithm,
compression_algorithm,
),
Command::List { archive, verbosity } => Self::list(archive, verbosity),
}
}

fn archive(
input: String,
output: String,
encryption: Option<SecretType>,
keypath: Option<String>,
verbosity: Verbosity,
encryption_algorithm: BinEncryptionType,
compression_algorithm: BinCompressionType,
compression_level: CompressionLevel,
) -> Result<(), ZapError> {
preamble(verbosity)?;

let enc: Option<EncryptionSecret> = match encryption {
Some(inner) => match inner {
SecretType::Password => Some(EncryptionSecret::Password(
match get_password_confirm(256) {
Ok(pass) => pass,
Err(e) => return Err(e.into()),
},
)),
SecretType::Key => match keypath {
Some(path) => Some(EncryptionSecret::Key(path)),
None => {
return Err(EncryptionSecretError::Key(
EncryptionKeyError::KeyfileNotProvided,
)
.into())
}
},
},
None => None,
let encryption_secret: EncryptionSecret = match (&encryption_algorithm, keypath) {
(BinEncryptionType::Passthrough, _) => EncryptionSecret::None,
(_, Some(path)) => EncryptionSecret::Key(path),
(_, None) => EncryptionSecret::Password(match get_password_confirm(256) {
Ok(pass) => pass,
Err(e) => return Err(e.into()),
}),
};

zap::compress_directory(&input, "/tmp/unpacked", enc)?;
info!("Encryption: {:?}", encryption_algorithm);
info!("Compression: {:?}", compression_algorithm);

zap::compress_directory(
&input,
"/tmp/unpacked",
encryption_algorithm.into(),
encryption_secret,
compression_algorithm.into(),
compression_level.into(),
zap::signing::SigningType::default(),
)?;

let out_file = File::create(output).expect("Could not create file");

Expand All @@ -147,38 +167,34 @@ impl Command {
fn extract(
input: String,
output: String,
decryption: Option<SecretType>,
keypath: Option<String>,
verbosity: Verbosity,
encryption_algorithm: BinEncryptionType,
compression_algorithm: BinCompressionType,
) -> Result<(), ZapError> {
preamble(verbosity)?;

let enc: Option<EncryptionSecret> = match decryption {
Some(inner) => match inner {
SecretType::Password => {
Some(EncryptionSecret::Password(match get_password_noconf(256) {
Ok(pass) => pass,
Err(e) => return Err(e.into()),
}))
}
SecretType::Key => match keypath {
Some(path) => Some(EncryptionSecret::Key(path)),
None => {
return Err(EncryptionSecretError::Key(
EncryptionKeyError::KeyfileNotProvided,
)
.into())
}
},
},
None => None,
let encryption_secret: EncryptionSecret = match (&encryption_algorithm, keypath) {
(BinEncryptionType::Passthrough, _) => EncryptionSecret::None,
(_, None) => EncryptionSecret::Password(match get_password_noconf(256) {
Ok(pass) => pass,
Err(e) => return Err(e.into()),
}),
(_, Some(path)) => EncryptionSecret::Key(path),
};

// Need to check if this function validates path names
// to prevent directory traversal.
unpack_files(input, "/tmp/unpacked")?;

zap::decompress_directory("/tmp/unpacked", &output, enc)?;
zap::decompress_directory(
"/tmp/unpacked",
&output,
encryption_algorithm.into(),
encryption_secret,
compression_algorithm.into(),
zap::signing::SigningType::default(),
)?;

Ok(fs::remove_dir_all("/tmp/unpacked")?)
//Ok(())
Expand Down
Loading

0 comments on commit b6b7dc4

Please sign in to comment.