Skip to content

Commit

Permalink
use ring crate for encryption, speed is much better, up to 800 MBps
Browse files Browse the repository at this point in the history
add Result on some methods which makes sense
switched tests to .unwrap() to panic
  • Loading branch information
radumarias committed May 3, 2024
1 parent 24465ef commit 9c1b963
Show file tree
Hide file tree
Showing 19 changed files with 1,124 additions and 674 deletions.
233 changes: 40 additions & 193 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ bincode = "1.3.3"
thiserror = "1.0.58"
rand = "0.8.5"
base64 = "=0.13.1"
openssl = "=0.10.64"
#openssl = "=0.10.64"
fuse3 = { version = "0.7.1", features = ["tokio-runtime", "unprivileged"] }
tokio = { version = "1.36", features = ["macros", "rt-multi-thread", "time", "signal", "process", "rt"] }
tokio-stream = { version = "0.1.15", features = ["fs"] }
Expand All @@ -39,14 +39,15 @@ sha2 = "0.11.0-pre.3"
strum = "0.26.2"
strum_macros = "0.26.2"
rpassword = "7.3.1"
cryptostream = "0.3.2"
#cryptostream = "0.3.2"
anyhow = "1.0.82"
argon2 = "0.5.3"
keyring = "2.3.2"
secrecy = "0.8.0"
retainer = "0.3.0"
num-format = "0.4.4"
aes-stream = "0.2.1"
ring = "0.17.8"
hex = "0.4.3"

[package.metadata.aur]
depends = ["fuse3"]
3 changes: 1 addition & 2 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ hex = "0.4.3"
fuser = "0.14.0"
env_logger = "0.11.3"
log = "0.4.21"
rust-crypto = "=0.2.36"

rust-crypto = { version = "0.2.36", package = "rust-crypto" }
```
2 changes: 1 addition & 1 deletion examples/aes_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::fs::OpenOptions;
use std::io::{Read, Seek, Write};
use aesstream::{AesReader, AesWriter};

use crypto::aessafe::{AesSafe256Decryptor, AesSafe256Encryptor};
use rust_crypto::aessafe::{AesSafe256Decryptor, AesSafe256Encryptor};

fn main() {
let key: [u8; 32] = "a".repeat(32).as_bytes().try_into().unwrap();
Expand Down
24 changes: 18 additions & 6 deletions examples/aes_stream_speed.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use std::fs::OpenOptions;
use std::io;
use std::io::Write;
use std::path::Path;
use std::time::Instant;

use aesstream::AesWriter;
use crypto::aessafe::AesSafe256Encryptor;
use aesstream::{AesReader, AesWriter};
use rust_crypto::aessafe::{AesSafe256Decryptor, AesSafe256Encryptor};

fn main() -> io::Result<()> {
let mut input = OpenOptions::new().read(true).open("/home/gnome/Downloads/Zero.Days.2016.720p.WEBRip.x264.AAC-ETRG/Zero.Days.2016.720p.WEBRip.x264.AAC-ETRG.mp4").unwrap();
let out_path = Path::new("./encrypted.enc");
let out = OpenOptions::new().create(true).write(true).open(out_path.clone())?;
let read_out = OpenOptions::new().read(true).open(out_path)?;
let mut input = OpenOptions::new().read(true).open("/home/gnome/Downloads/bfg-1.14.0.jar").unwrap();
let out_path = Path::new("/tmp/encrypted.enc");
let out = OpenOptions::new().create(true).write(true).truncate(true).open(out_path.clone())?;

let key: [u8; 32] = "a".repeat(32).as_bytes().try_into().unwrap();
let encryptor = AesSafe256Encryptor::new(&key);
Expand All @@ -23,5 +23,17 @@ fn main() -> io::Result<()> {
let file_size = input.metadata()?.len();
println!("speed MB/s {}", (file_size as f64 / end.duration_since(start).as_secs_f64()) / 1024.0 / 1024.0);

let input = OpenOptions::new().read(true).open(out_path).unwrap();
let out_path = Path::new("/tmp/encrypted.dec");
let mut out = OpenOptions::new().create(true).write(true).truncate(true).open(out_path.clone())?;
let decryptor = AesSafe256Decryptor::new(&key);
let mut reader = AesReader::new(input, decryptor)?;
let start = Instant::now();
io::copy(&mut reader, &mut out)?;
let end = Instant::now();
println!("Time elapsed: {:?}", end.duration_since(start));
let file_size = out_path.metadata()?.len();
println!("speed MB/s {}", (file_size as f64 / end.duration_since(start).as_secs_f64()) / 1024.0 / 1024.0);

Ok(())
}
2 changes: 1 addition & 1 deletion examples/cryptostream_speed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fn main() -> io::Result<()> {

let mut input = OpenOptions::new().read(true).open("/home/gnome/Downloads/Zero.Days.2016.720p.WEBRip.x264.AAC-ETRG/Zero.Days.2016.720p.WEBRip.x264.AAC-ETRG.mp4").unwrap();
let out_path = Path::new("./encrypted.enc");
let out = OpenOptions::new().create(true).write(true).open(out_path)?;
let out = OpenOptions::new().create(true).write(true).truncate(true).open(out_path)?;

let mut encryptor = write::Encryptor::new(out, Cipher::chacha20(), &key, &iv).unwrap();

Expand Down
21 changes: 21 additions & 0 deletions examples/ring.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use ring::aead::{Aad, CHACHA20_POLY1305, LessSafeKey, Nonce, UnboundKey};

fn main() {
let key = [42; 32];
let nonce_data = [124; 12]; // Just an example
let mut data = b"hello, this is my secret message".to_vec();

let key = UnboundKey::new(&CHACHA20_POLY1305, &key).unwrap();
let key = LessSafeKey::new(key);
println!("{data:?}");

// encoding
let nonce = Nonce::assume_unique_for_key(nonce_data);
key.seal_in_place_append_tag(nonce, Aad::empty(), &mut data).unwrap();
println!("{data:?}");

// decoding
let nonce = Nonce::assume_unique_for_key(nonce_data);
let data = key.open_in_place(nonce, Aad::empty(), &mut data).unwrap();
println!("{data:?}");
}
108 changes: 108 additions & 0 deletions examples/ring_crypto.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use std::fs::{File, OpenOptions};
use std::io::{Read, Write};
use std::path::PathBuf;

use argon2::password_hash::rand_core::RngCore;
use rand::thread_rng;
use ring::aead::{AES_256_GCM, CHACHA20_POLY1305};
use secrecy::{ExposeSecret, SecretString, SecretVec};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use tokio::fs;

use rencfs::crypto;
use rencfs::crypto::Cipher;
use rencfs::crypto::encryptor::CryptoWriter;
use rencfs::encryptedfs::FsError;

fn main() {
// let password = SecretString::new("password".to_string());
// let salt = crypto::hash_secret(&password);
// let cipher = Cipher::ChaCha20;
// let key = crypto::derive_key(&password, &cipher, salt).unwrap();
//
// let cipher = Cipher::ChaCha20;
//
// let path = PathBuf::from("/tmp/test.txt");
// let mut writer = crypto::create_crypto_writer(OpenOptions::new().read(true).write(true).create(true).open(path.clone()).unwrap(),
// &cipher, &key);
// let x = "Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world!".to_string();
// bincode::serialize_into(&mut writer, &x).unwrap();
// // writer.write_all(x.as_bytes()).unwrap();
// writer.flush().unwrap();
// writer.finish().unwrap();
//
// let mut reader = crypto::create_crypto_reader(File::open(path).unwrap(), &cipher, &key);
// let mut buf = vec![0; x.len()];
// // reader.read_exact(&mut buf).unwrap();
// let dec: String = bincode::deserialize_from(&mut reader).unwrap();
// // let dec = String::from_utf8(buf).unwrap();
// println!("{}", dec);
// assert_eq!(dec, x);

// derive key from password
let password = SecretString::new("password".to_string());
let salt = crypto::hash_secret(&password);
let cipher = Cipher::ChaCha20;
let derived_key = crypto::derive_key(&password, &cipher, salt).unwrap();
let path = PathBuf::from("/tmp/key.enc");
let _ = fs::remove_file(&path);

// first time, create a random key and encrypt it with the derived key from password

let mut key: Vec<u8> = vec![];
let key_len = match cipher {
Cipher::ChaCha20 => CHACHA20_POLY1305.key_len(),
Cipher::Aes256Gcm => AES_256_GCM.key_len(),
};
key.resize(key_len, 0);
thread_rng().fill_bytes(&mut key);
println!("key: {:?}", key);
let key = SecretVec::new(key);
let key_store = KeyStore::new(key);
println!("hash {:?}", key_store.hash);
let mut writer = crypto::create_crypto_writer(OpenOptions::new().read(true).write(true).create(true).open(path.clone()).unwrap(),
&cipher, &derived_key);
bincode::serialize_into(&mut writer, &key_store).unwrap();
writer.flush().unwrap();
writer.finish().unwrap();

// read key

let reader = crypto::create_crypto_reader(File::open(path).unwrap(), &cipher, &derived_key);
let key_store: KeyStore = bincode::deserialize_from(reader).map_err(|_| FsError::InvalidPassword).unwrap();
println!("key {:?}", key_store.key.expose_secret());
println!("hash {:?}", key_store.hash);
// check hash
if key_store.hash != crypto::hash(key_store.key.expose_secret()) {
eprintln!("Invalid password");
return;
}
}

fn key_serialize<S>(key: &SecretVec<u8>, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
s.collect_seq(key.expose_secret())
}

fn key_unserialize<'de, D>(deserializer: D) -> Result<SecretVec<u8>, D::Error>
where D: Deserializer<'de> {
let vec = Vec::deserialize(deserializer)?;
Ok(SecretVec::new(vec))
}

#[derive(Serialize, Deserialize)]
struct KeyStore {
#[serde(serialize_with = "key_serialize")]
#[serde(deserialize_with = "key_unserialize")]
key: SecretVec<u8>,
hash: [u8; 32],
}

impl KeyStore {
fn new(key: SecretVec<u8>) -> Self {
let hash = crypto::hash(key.expose_secret());
Self { key, hash }
}
}
107 changes: 92 additions & 15 deletions examples/ring_speed.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::fs::OpenOptions;
use std::io::{Read, Write};
use std::io;
use std::io::{BufReader, BufWriter, Read, Write};
use std::path::Path;
use ring::error::Unspecified;
use ring::rand::SecureRandom;
use ring::rand::SystemRandom;
use ring::aead::Algorithm;
use ring::aead::{Algorithm, LessSafeKey};
use ring::aead::AES_128_GCM;
use ring::aead::AES_256_GCM;
use ring::aead::CHACHA20_POLY1305;
Expand All @@ -28,17 +29,17 @@ impl NonceSequence for CounterNonceSequence {

let bytes = self.0.to_be_bytes();
nonce_bytes[8..].copy_from_slice(&bytes);
println!("nonce_bytes = {}", hex::encode(&nonce_bytes));
// println!("nonce_bytes = {}", hex::encode(&nonce_bytes));

self.0 += 1; // advance the counter
Nonce::try_assume_unique_for_key(&nonce_bytes)
}
}

fn main() -> std::io::Result<()> {
fn main() -> io::Result<()> {
let mut input = OpenOptions::new().read(true).open("/home/gnome/Downloads/Zero.Days.2016.720p.WEBRip.x264.AAC-ETRG/Zero.Days.2016.720p.WEBRip.x264.AAC-ETRG.mp4").unwrap();
let out_path = Path::new("./encrypted.enc");
let mut out = OpenOptions::new().create(true).write(true).open(out_path)?;
let out_path = Path::new("/tmp/encrypted.enc");
let mut out = OpenOptions::new().create(true).write(true).truncate(true).open(out_path)?;

// Create a new instance of SystemRandom to be used as the single source of entropy
let rand = SystemRandom::new();
Expand All @@ -59,31 +60,107 @@ fn main() -> std::io::Result<()> {
let mut sealing_key = SealingKey::new(unbound_key, nonce_sequence);

// This data will be authenticated but not encrypted
//let associated_data = Aad::empty(); // is optional so can be empty
let associated_data = Aad::from(b"additional public data");
// let associated_data = Aad::empty(); // is optional so can be empty
// let associated_data = Aad::from(b"additional public data");

let file_size = input.metadata()?.len();

let mut input = BufReader::new(input);
let mut out = BufWriter::new(out);

let start = std::time::Instant::now();
let mut buffer = [0; 4096];
let mut buffer = vec![0; 4096];
loop {
let len = input.read(&mut buffer).unwrap();
let len = {
let mut pos = 0;
loop {
match input.read(&mut buffer[pos..]) {
Ok(read) => {
pos += read;
if read == 0 {
break;
}
}
Err(err) => return Err(err),
}
}
pos
};
if len == 0 {
break;
}
if len != buffer.len() {
println!("len = {}", len);
}
// Data to be encrypted
let data = buffer[..len].to_vec();
let mut data = &mut buffer[..len];
// let mut data = buffer[..len].to_vec();

// Create a mutable copy of the data that will be encrypted in place
let mut in_out = data.clone();
// let mut in_out = data.clone();

// Encrypt the data with AEAD using the AES_256_GCM algorithm
let tag = sealing_key.seal_in_place_separate_tag(associated_data, &mut in_out).unwrap();
let tag = sealing_key.seal_in_place_separate_tag(Aad::empty(), &mut data).unwrap();

out.write(&in_out).unwrap();
out.write(&data).unwrap();
out.write(tag.as_ref()).unwrap();
}
out.flush().unwrap();
let end = std::time::Instant::now();
let duration = end.duration_since(start);
let file_size = input.metadata()?.len();
println!("duration = {:?}", duration);
println!("speed MB/s {}", (file_size as f64 / duration.as_secs_f64()) / 1024.0 / 1024.0);

// decrypt
let unbound_key = UnboundKey::new(&CHACHA20_POLY1305, &key_bytes).unwrap();
let nonce_sequence = CounterNonceSequence(1);
let mut opening_key = OpeningKey::new(unbound_key, nonce_sequence);

let input = OpenOptions::new().read(true).open(out_path).unwrap();
let out = OpenOptions::new().create(true).write(true).truncate(true).open(Path::new("/tmp/encrypted.dec"))?;

let start = std::time::Instant::now();
let mut buffer = vec![0; 4096 + CHACHA20_POLY1305.tag_len()];
let mut input = BufReader::new(input);
let mut out = BufWriter::new(out);
loop {
let len = {
let mut pos = 0;
loop {
match input.read(&mut buffer[pos..]) {
Ok(read) => {
pos += read;
if read == 0 {
break;
}
}
Err(err) => return Err(err),
}
}
pos
};
if len == 0 {
break;
}
if len != buffer.len() {
println!("len = {}", len);
}
// Data to be encrypted
let mut data = &mut buffer[..len];

// Create a mutable copy of the data that will be encrypted in place
// let mut in_out = data.clone();

// Encrypt the data with AEAD using the AES_256_GCM algorithm
let dec = opening_key.open_within(Aad::empty(), &mut data, 0..).unwrap();
// let dec = opening_key.open_in_place(Aad::empty(), &mut data).unwrap();

out.write(&dec).unwrap();
}
out.flush().unwrap();
let end = std::time::Instant::now();
let duration = end.duration_since(start);
// let file_size = input.metadata()?.len();
println!("duration = {:?}", duration);
println!("speed MB/s {}", (file_size as f64 / duration.as_secs_f64()) / 1024.0 / 1024.0);

Expand Down
Loading

0 comments on commit 9c1b963

Please sign in to comment.