Skip to content

Commit

Permalink
feat: add cli
Browse files Browse the repository at this point in the history
  • Loading branch information
mikesposito committed Nov 29, 2023
1 parent 68cc19a commit 647386e
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 30 deletions.
39 changes: 39 additions & 0 deletions .github/workflows/build-lint-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Build, Lint and Test

on:
push:
branches: [ main ]
pull_request:

env:
CARGO_TERM_COLOR: always

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Build
run: cargo build --workspace --verbose

lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Lint
run: |
rustfmt ./**/*.rs
if ! git diff --exit-code; then
echo "Please run 'rustfmt --check ./**/*.rs' to lint your code."
exit 1
fi
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Text
run: cargo test --workspace
25 changes: 12 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ path = "enclave"
version = "^4.0.0"
features = ["derive"]

[dependencies.text_io]
version = "^0.1.12"

[[bin]]
name = "secured"
path = "src/main.rs"
69 changes: 69 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# 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.

## Features

- **Encryption and Decryption**: Easily encrypt and decrypt files with password, safely.
- **Cli & Library**: Use as a standalone CLI tool or integrate as a library in your Rust applications.

## Installation

To use **secured** as a CLI tool or integrate it into your Rust project, ensure you have Rust installed, then add Secured to your dependencies:

```sh
cargo add secured
```

## Usage

### As a CLI Tool

Secured is straightforward to use from the command line. Here are the basic commands:

1. **Encryption**
```sh
secured encrypt <FILE> [PASSWORD]
```
Encrypts the specified `<file>`. An optional `<password>` can be provided for extra security.

2. **Decryption**
```sh
secured decrypt <FILE> [PASSWORD]
```
Decrypts the specified `<file>`. If a `<password>` was used during encryption, the same must be provided for decryption.

### As a Library

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.

## Examples

Here's a quick example of how to use Secured in your Rust code:

```rust
use secured::{encrypt, decrypt};

fn main() {
let file_path = "path/to/your/file";
let password = Some("your_password");

// Encrypt a file
encrypt(file_path, password).expect("Encryption failed");

// Decrypt a file
decrypt(file_path, password).expect("Decryption failed");
}
```

## Contributing

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.

---

Feel free to modify and expand this README as per your project's evolving needs!
4 changes: 2 additions & 2 deletions enclave/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ version = "~0.12.2"
version = "~0.6.4"
features = ["getrandom"]

[dependencies.sha3]
version = "~0.10.8"
[dependencies.sha2]
version = "~0.10.5"
8 changes: 4 additions & 4 deletions enclave/src/encryption_key.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use hmac::Hmac;
use pbkdf2::pbkdf2;
use rand_core::{OsRng, RngCore};
use sha3::Keccak256;
use sha2::Sha256;

/// A Public Key & Salt pair that can be used for simmetric encryption,
/// A Public Key & Salt pair that can be used for symmetric encryption,
/// compatible with ChaCha20Poly1305
pub struct EncryptionKey {
pub pubk: [u8; 32],
Expand All @@ -19,7 +19,7 @@ impl EncryptionKey {

// Key derivation
let mut pubk = [0; 32];
if pbkdf2::<Hmac<Keccak256>>(password, &salt, rounds, &mut pubk).is_err() {
if pbkdf2::<Hmac<Sha256>>(password, &salt, rounds, &mut pubk).is_err() {
panic!("Key derivation failed")
}

Expand All @@ -31,7 +31,7 @@ impl EncryptionKey {
pub fn with_salt(password: &[u8], salt: [u8; 16], rounds: u32) -> Self {
// Key derivation
let mut pubk = [0; 32];
if pbkdf2::<Hmac<Keccak256>>(password, &salt, rounds, &mut pubk).is_err() {
if pbkdf2::<Hmac<Sha256>>(password, &salt, rounds, &mut pubk).is_err() {
panic!("Key derivation failed")
}

Expand Down
1 change: 1 addition & 0 deletions enclave/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::fmt::{Display, Formatter, Result};

#[derive(Debug)]
pub enum EnclaveError {
Serialization(String),
Deserialization(String),
Expand Down
101 changes: 90 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,98 @@
use clap::Parser;
use enclave::Enclave;
use std::fs::{metadata, File};
use std::io::{Read, Write};
use text_io::read;

#[derive(Parser, Debug)]
struct CliArgs {
#[arg(short, long)]
password: Option<String>,
use clap::{Parser, Subcommand};
use enclave::{Enclave, EncryptionKey};

#[derive(Debug, Subcommand)]
enum Command {
Encrypt {
file: String,
password: Option<String>,
},
Decrypt {
file: String,
password: Option<String>,
},
}

#[arg(short, long)]
file: String,
#[derive(Parser, Debug)]
struct Args {
#[command(subcommand)]
command: Command,
}

fn main() {
let args = CliArgs::parse();
let args = Args::parse();

match args.command {
Command::Encrypt { file, password } => {
let password = get_password_or_prompt(password);
encrypt_file(&password, &file);
}
Command::Decrypt { file, password } => {
let password = get_password_or_prompt(password);
decrypt_file(&password, &file);
}
}
}

fn encrypt_file(password: &String, filename: &String) {
println!("Encrypting file: {}", filename);
let encryption_key = EncryptionKey::new(password.as_bytes(), 900_000);
println!("encryption_key: {:?}", encryption_key.pubk);
let enclave = Enclave::from_plain_bytes(
encryption_key.salt,
&encryption_key.pubk,
get_file_as_byte_vec(filename),
)
.unwrap();
let encrypted_bytes: Vec<u8> = enclave.into();
println!("encrypted_bytes: {:?}", encrypted_bytes);

File::create(format!("{}.secured", filename))
.expect("Unable to create file")
.write_all(&encrypted_bytes)
.expect("Unable to write data");

println!("{:?}", args);
println!("Wrote encrypted file to {}.secured", filename);
}

fn decrypt_file(password: &String, filename: &String) {
let encrypted_bytes = get_file_as_byte_vec(filename);
let enclave = Enclave::try_from(encrypted_bytes).expect("Unable to deserialize enclave");
let encryption_key = EncryptionKey::with_salt(password.as_bytes(), enclave.metadata, 900_000);
let recovered_bytes = enclave
.decrypt(&encryption_key.pubk)
.expect("Wrong password or corrupted enclave");

File::create(filename.replace(".secured", ""))
.expect("Unable to create file")
.write_all(&recovered_bytes)
.expect("Unable to write data");

println!(
"Wrote decrypted file to {}",
filename.replace(".enclave", "")
);
}

fn get_file_as_byte_vec(filename: &String) -> Vec<u8> {
let mut f = File::open(&filename).expect("no file found");
let metadata = metadata(&filename).expect("unable to read metadata");
let mut buffer = vec![0; metadata.len() as usize];
f.read(&mut buffer).expect("buffer overflow");

buffer
}

println!("Hello, world!");
fn get_password_or_prompt(password: Option<String>) -> String {
match password {
Some(password) => password,
None => {
println!("Enter password: ");
read!("{}\n")
}
}
}

0 comments on commit 647386e

Please sign in to comment.