Skip to content

Commit

Permalink
feat: complete cli additions
Browse files Browse the repository at this point in the history
  • Loading branch information
mikesposito committed Dec 19, 2023
1 parent 2e1e544 commit 6c6c22b
Show file tree
Hide file tree
Showing 6 changed files with 288 additions and 131 deletions.
115 changes: 85 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# secured

Secured is a versatile Rust package that provides robust encryption and decryption capabilities. It can be seamlessly integrated as a library in other Rust applications or used as a standalone command-line interface (CLI) tool.
A very fast CLI tool for encryption and decryption of large amounts of data

> [!WARNING]
> This crate is under development and APIs are rapidly changing (including this README!). Make sure to lock to a specific crate version to avoid updates.
> As this crate is under early development, APIs are rapidly changing, and so is the documentation.
## Features

- **Encryption and Decryption**: Easily encrypt and decrypt files with password, using [the `ChaCha20` and `Poly1305` algorithms combined](cipher/README.md).
- **Cli & Library**: Use as a standalone CLI tool or integrate as a library in your Rust applications.
- **Encryption and Decryption**: Easily encrypt and decrypt files with password or a pre-generated encryption key.
- **Key Derivation**: Generate encryption keys from passwords with customizable iterations and salt.
- **File Inspection**: Inspect details of secured files.

## Installation

Expand All @@ -28,49 +29,100 @@ cargo add secured

## Usage

### As a CLI Tool
### Encrypting a Single File

Secured is straightforward to use from the command line. Here are the basic commands:
Encrypt a single file with a password. If no password is provided, the tool will prompt you for it.

1. **Encryption**
```sh
secured encrypt secret.txt
```

### Decrypting a Single File

```sh
secured encrypt <FILE> [PASSWORD]
```
Decrypt a single file with a password. If no password is provided, the tool will prompt you for it.

Encrypts the specified `<FILE>`. An optional `[PASSWORD]` can be passed directly to the command.
```sh
secured decrypt secret.txt.secured
```

2. **Decryption**
```sh
secured decrypt <FILE> [PASSWORD]
```
Decrypts the specified `<FILE>`. An optional `[PASSWORD]` can be passed directly to the command. Obviously, the password must be the same used during encryption.
### Encrypting/Decrypting Multiple Files with Glob Patterns

### As a Library
Use glob patterns to encrypt or decrypt multiple files with a single command.

```sh
secured encrypt data/*.txt
secured decrypt data/*.txt.secured
```

### Generating Encryption Key

Generate an encryption key from a password with customizable iterations and salt.

```sh
secured key --password my_secret_password --iterations 1000000 --salt abcdef1234567890
```

### Inspecting Secured Files

Inspect details of one or more secured files.

```sh
secured inspect secret.txt.secured
secured inspect data/*.txt.secured
```

## Examples

### Encrypting a Single File

To use Secured as a library in your Rust application, simply import the package and utilize its encryption and decryption functions as per your requirements.
```sh
secured encrypt secret.txt
```

### Decrypting a Single File

#### Encrypting Data
```sh
secured decrypt secret.txt.secured
```

```rust
use secured_enclave::{Enclave, Encryptable, KeyDerivationStrategy};
### Encrypting/Decrypting Multiple Files with Glob Patterns

let password = "strong_password";
let encrypted_string = "Hello, world!".encrypt(password.to_string(), KeyDerivationStrategy::default());
```sh
secured encrypt data/*.txt
secured decrypt data/*.txt.secured
```

#### Decrypting Data
### Generating Encryption Key

```rust
use secured_enclave::{Decryptable, EnclaveError};
```sh
secured key --password my_secret_password --iterations 1000000 --salt abcdef1234567890
```

let password = "strong_password";
let decrypted_result = encrypted_data.decrypt(password.to_string());
### Inspecting Secured Files

println!("Decrypted data: {:?}", String::from_utf8(decrypted_data).unwrap())
```sh
secured inspect secret.txt.secured
secured inspect data/*.txt.secured
```

See [Enclave documentation](enclave/README.md) for more advanced usage
## Advanced Usage

### Customizing Key Derivation

For advanced users, customize key derivation options during key generation.

```sh
secured key --password my_secret_password --iterations 1500000 --salt 1a2b3c4d...
```

### Integrating with Scripts

Integrate **secured** into your scripts for automated encryption and decryption tasks.

```sh
#!/bin/bash
secured encrypt data/*.csv --key $ENCRYPTION_KEY
```

## Contributing

Expand All @@ -79,3 +131,6 @@ Contributions are welcome! Feel free to open issues or submit pull requests.
## License

Secured is distributed under the MIT License. See `LICENSE` for more information.
```
This version of the README emphasizes examples with single files and no options, showcasing the tool's ability to prompt for a password when needed. It then introduces examples with glob patterns for handling multiple files in a single command.
3 changes: 0 additions & 3 deletions benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,3 @@ secured-cipher = { path = "../cipher/" }
name = "chacha20"
path = "src/chacha20.rs"
harness = false

[profile.bench]
debug = true
2 changes: 1 addition & 1 deletion enclave/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Add the following line to your `Cargo.toml` file:

```toml
[dependencies]
enclave = "0.5.0"
secured-enclave = "0.5.0"
```

## Usage
Expand Down
34 changes: 32 additions & 2 deletions enclave/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ pub struct Enclave<T> {
pub metadata: T,

/// The encrypted data.
encrypted_bytes: Box<[u8]>,
pub encrypted_bytes: Box<[u8]>,

/// The nonce used in the encryption process, 8 bytes long (ChaCha20).
nonce: [u8; NONCE_SIZE],
pub nonce: [u8; NONCE_SIZE],
}

impl<T> Enclave<T>
Expand Down Expand Up @@ -81,6 +81,28 @@ where
.decrypt_and_verify(&envelope)?,
)
}

/// Recovers the key used to encrypt the enclave using a provided password.
///
/// # Arguments
/// * `encrypted_bytes`: The encrypted enclave.
///
/// # Returns
/// A `Result` containing the recovered key, or an error string if recovery fails.
pub fn recover_key(
encrypted_bytes: &[u8],
password: &[u8],
) -> Result<Key<KEY_SIZE, 16>, EnclaveError> {
let strategy = KeyDerivationStrategy::try_from(
encrypted_bytes[encrypted_bytes.len() - 9..encrypted_bytes.len()].to_vec(),
)?;
let salt: [u8; 16] = encrypted_bytes[encrypted_bytes.len() - 25..encrypted_bytes.len() - 9]
.try_into()
.unwrap();
let key = Key::<KEY_SIZE, 16>::with_salt(password, salt, strategy);

Ok(key)
}
}

impl<T> From<Enclave<T>> for Vec<u8>
Expand Down Expand Up @@ -121,7 +143,15 @@ where
/// # Returns
/// A `Result` containing the deserialized `Enclave` instance, or an `EnclaveError` if deserialization fails.
fn try_from(bytes: Vec<u8>) -> Result<Self, EnclaveError> {
if bytes.len() == 0 {
return Err(EnclaveError::Deserialization("No bytes found".to_string()));
}
let metadata_len = bytes[0];
if usize::from(metadata_len) > bytes.len() {
return Err(EnclaveError::Deserialization(
"unexpected metadata length".to_string(),
));
}
let metadata = T::try_from(bytes[1..metadata_len as usize + 1].to_vec()).or(Err(
EnclaveError::Deserialization("error deserializing metadata".to_string()),
))?;
Expand Down
41 changes: 31 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use clap::{Parser, Subcommand};

mod utils;
pub use utils::{decrypt_files, encrypt_files};
use utils::{generate_encryption_key_with_options, get_password_or_prompt, Credentials};
use utils::{
generate_encryption_key_with_options, get_password_or_prompt, inspect_files, Credentials,
};

/// Defines command line subcommands for the application.
#[derive(Debug, Subcommand)]
Expand All @@ -20,7 +22,12 @@ enum Command {
/// If provided, the password will be ignored.
#[arg(short, long)]
key: Option<String>,

/// Wipe the original file after encryption.
#[arg(short, long)]
wipe: bool,
},

/// Decrypts a specified file.
Decrypt {
/// Path to the files to be decrypted. Supports glob patterns.
Expand All @@ -34,7 +41,12 @@ enum Command {
/// If provided, the password will be ignored.
#[arg(short, long)]
key: Option<String>,

/// Wipe the encrypted file after decryption.
#[arg(short, long)]
wipe: bool,
},

/// Derives a key from a given password.
Key {
/// Optional password. If not provided, it will be prompted for.
Expand All @@ -51,6 +63,12 @@ enum Command {
#[arg(short, long)]
salt: Option<String>,
},

/// Inspects a specified `.secured` file.
Inspect {
/// Path to the files to be inspected. Supports glob patterns.
path: Vec<String>,
},
}

/// Defines the command line arguments structure.
Expand All @@ -70,31 +88,34 @@ fn main() {
path,
password,
key,
wipe,
} => match key {
Some(key) => encrypt_files(&Credentials::HexKey(key), path),
Some(key) => encrypt_files(&Credentials::HexKey(key), path, wipe),
None => {
let password = get_password_or_prompt(password);
encrypt_files(&Credentials::Password(password), path);
let password = get_password_or_prompt(password, true);
encrypt_files(&Credentials::Password(password), path, wipe);
}
},
Command::Decrypt {
path,
password,
key,
} => match key {
Some(key) => decrypt_files(&Credentials::HexKey(key), path),
wipe,
} => match key {
Some(key) => decrypt_files(&Credentials::HexKey(key), path, wipe),
None => {
let password = get_password_or_prompt(password);
decrypt_files(&Credentials::Password(password), path);
let password = get_password_or_prompt(password, false);
decrypt_files(&Credentials::Password(password), path, wipe);
}
}
},
Command::Key {
password,
iterations,
salt,
} => {
let password = get_password_or_prompt(password);
let password = get_password_or_prompt(password, true);
generate_encryption_key_with_options(&password, iterations, salt);
}
Command::Inspect { path } => inspect_files(path),
}
}
Loading

0 comments on commit 6c6c22b

Please sign in to comment.