mirror of
https://github.com/CompeyDev/ruck.git
synced 2025-01-08 11:49:09 +00:00
Encrypt
This commit is contained in:
parent
e934171a2b
commit
f4c7f1361e
8 changed files with 173 additions and 23 deletions
72
Cargo.lock
generated
72
Cargo.lock
generated
|
@ -188,7 +188,7 @@ checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"digest 0.9.0",
|
"digest 0.9.0",
|
||||||
"rand_core",
|
"rand_core 0.5.1",
|
||||||
"subtle",
|
"subtle",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
@ -346,7 +346,18 @@ checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -614,6 +625,12 @@ dependencies = [
|
||||||
"universal-hash",
|
"universal-hash",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-error"
|
name = "proc-macro-error"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
@ -656,13 +673,53 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core 0.6.3",
|
||||||
|
"rand_hc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core 0.6.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom 0.1.16",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.2.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_hc"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.6.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -685,6 +742,7 @@ dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"clap",
|
"clap",
|
||||||
"futures",
|
"futures",
|
||||||
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
"spake2",
|
"spake2",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -759,7 +817,7 @@ checksum = "7139ade210556eca57dfc299ec2454846ab6be09232eb1139a36e285ae7fd48e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"curve25519-dalek",
|
"curve25519-dalek",
|
||||||
"hkdf",
|
"hkdf",
|
||||||
"rand_core",
|
"rand_core 0.5.1",
|
||||||
"sha2",
|
"sha2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -907,6 +965,12 @@ version = "0.9.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.10.2+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|
|
@ -12,6 +12,7 @@ bytes = { version = "1", features = ["serde"] }
|
||||||
bincode = "1.3.3"
|
bincode = "1.3.3"
|
||||||
clap = { version = "3.0.14", features = ["derive"] }
|
clap = { version = "3.0.14", features = ["derive"] }
|
||||||
futures = { version = "0.3.0", features = ["thread-pool"]}
|
futures = { version = "0.3.0", features = ["thread-pool"]}
|
||||||
|
rand = "0.8.4"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
spake2 = "0.3.1"
|
spake2 = "0.3.1"
|
||||||
tokio = { version = "1.16.1", features = ["full"] }
|
tokio = { version = "1.16.1", features = ["full"] }
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use crate::crypto::handshake;
|
use crate::crypto::handshake;
|
||||||
|
use crate::file::FileHandle;
|
||||||
use crate::message::{Message, MessageStream};
|
use crate::message::{Message, MessageStream};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use blake2::{Blake2s256, Digest};
|
use blake2::{Blake2s256, Digest};
|
||||||
use bytes::{BufMut, Bytes, BytesMut};
|
use bytes::{BufMut, Bytes, BytesMut};
|
||||||
|
use futures::future::join_all;
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
|
@ -16,6 +18,13 @@ fn pass_to_bytes(password: &String) -> Bytes {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(file_paths: &Vec<PathBuf>, password: &String) -> Result<()> {
|
pub async fn send(file_paths: &Vec<PathBuf>, password: &String) -> Result<()> {
|
||||||
|
let tasks = file_paths
|
||||||
|
.into_iter()
|
||||||
|
.map(|path| FileHandle::new(path.to_path_buf()).map(|f| f.map(|s| s.to_file_info())));
|
||||||
|
let metadatas = join_all(tasks).await;
|
||||||
|
println!("mds: {:?}", metadatas);
|
||||||
|
return Ok(());
|
||||||
|
|
||||||
let socket = TcpStream::connect("127.0.0.1:8080").await?;
|
let socket = TcpStream::connect("127.0.0.1:8080").await?;
|
||||||
let mut stream = Message::to_stream(socket);
|
let mut stream = Message::to_stream(socket);
|
||||||
|
|
||||||
|
@ -27,21 +36,7 @@ pub async fn send(file_paths: &Vec<PathBuf>, password: &String) -> Result<()> {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
return upload_encrypted_files(stream, file_paths, key).await;
|
// return upload_encrypted_files(stream, file_paths, key).await;
|
||||||
|
|
||||||
// Send the value
|
|
||||||
// for path in paths.iter() {
|
|
||||||
// let b = path.to_str().unwrap().as_bytes();
|
|
||||||
// let mut buf = BytesMut::with_capacity(1024);
|
|
||||||
// buf.put(&b[..]);
|
|
||||||
// let body = buf.freeze();
|
|
||||||
// let m = Message {
|
|
||||||
// key: "abc".to_string(),
|
|
||||||
// from_sender: true,
|
|
||||||
// body: body,
|
|
||||||
// };
|
|
||||||
// stream.send(m).await.unwrap();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn receive(password: &String) -> Result<()> {
|
pub async fn receive(password: &String) -> Result<()> {
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
use crate::message::{HandshakePayload, Message, MessageStream};
|
use crate::message::{EncryptedPayload, HandshakePayload, Message, MessageStream};
|
||||||
|
|
||||||
|
use aes_gcm::aead::{Aead, NewAead};
|
||||||
|
use aes_gcm::{Aes256Gcm, Key, Nonce}; // Or `Aes128Gcm`
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
|
use rand::{thread_rng, Rng};
|
||||||
use spake2::{Ed25519Group, Identity, Password, Spake2};
|
use spake2::{Ed25519Group, Identity, Password, Spake2};
|
||||||
|
|
||||||
pub async fn handshake(
|
pub async fn handshake(
|
||||||
|
@ -38,3 +41,32 @@ pub async fn handshake(
|
||||||
println!("Handshake successful. Key is {:?}", key);
|
println!("Handshake successful. Key is {:?}", key);
|
||||||
return Ok((stream, Bytes::from(key)));
|
return Ok((stream, Bytes::from(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_cypher(key: Bytes) -> Aes256Gcm {
|
||||||
|
let key = Key::from_slice(&key[..]);
|
||||||
|
Aes256Gcm::new(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
const NONCE_SIZE_IN_BYTES: usize = 96 / 8;
|
||||||
|
|
||||||
|
pub fn encrypt(cipher: &Aes256Gcm, body: Bytes) -> Result<EncryptedPayload> {
|
||||||
|
let mut arr = [0u8; NONCE_SIZE_IN_BYTES];
|
||||||
|
thread_rng().try_fill(&mut arr[..])?;
|
||||||
|
let nonce = Nonce::from_slice(&arr);
|
||||||
|
let plaintext = body.as_ref();
|
||||||
|
match cipher.encrypt(nonce, plaintext) {
|
||||||
|
Ok(ciphertext) => Ok(EncryptedPayload {
|
||||||
|
nonce: Bytes::from(&arr[..]),
|
||||||
|
body: Bytes::from(ciphertext.as_ref()),
|
||||||
|
}),
|
||||||
|
Err(_) => anyhow!("Encryption error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decrypt(cipher: &Aes256Gcm, payload: EncryptedPayload) -> Result<Bytes> {
|
||||||
|
let nonce = Nonce::from_slice(payload.nonce.as_ref());
|
||||||
|
match cipher.decrypt(nonce, payload.body.as_ref()) {
|
||||||
|
Ok(_) => Ok(Bytes::from("hello")),
|
||||||
|
Err(_) => anyhow!("Decryption error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
51
src/file.rs
Normal file
51
src/file.rs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::ffi::OsString;
|
||||||
|
use std::fs::Metadata;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use tokio::fs::File;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct FileInfo {
|
||||||
|
name: OsString,
|
||||||
|
size: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FileHandle {
|
||||||
|
file: File,
|
||||||
|
md: Metadata,
|
||||||
|
path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileHandle {
|
||||||
|
pub async fn new(path: PathBuf) -> Result<FileHandle> {
|
||||||
|
let file = File::open(&path).await?;
|
||||||
|
let md = file.metadata().await?;
|
||||||
|
let fh = FileHandle { file, md, path };
|
||||||
|
return Ok(fh);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_file_info(&self) -> FileInfo {
|
||||||
|
FileInfo {
|
||||||
|
name: match self.path.file_name() {
|
||||||
|
Some(s) => s.to_os_string(),
|
||||||
|
None => OsString::from("Unknown"),
|
||||||
|
},
|
||||||
|
size: self.md.len(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const SUFFIX: [&'static str; 9] = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
||||||
|
// Stolen: https://gitlab.com/forkbomb9/human_bytes-rs/-/blob/master/src/lib.rs
|
||||||
|
pub fn to_size_string(size: f64) -> String {
|
||||||
|
let base = size.log10() / 1024_f64.log10();
|
||||||
|
let mut result = format!("{:.1}", 1024_f64.powf(base - base.floor()),)
|
||||||
|
.trim_end_matches(".0")
|
||||||
|
.to_owned();
|
||||||
|
// Add suffix
|
||||||
|
result.push(' ');
|
||||||
|
result.push_str(SUFFIX[base.floor() as usize]);
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
mod cli;
|
mod cli;
|
||||||
mod client;
|
mod client;
|
||||||
mod crypto;
|
mod crypto;
|
||||||
|
mod file;
|
||||||
mod message;
|
mod message;
|
||||||
mod server;
|
mod server;
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
match &args.command {
|
match &args.command {
|
||||||
Commands::Send { paths, password } => {
|
Commands::Send { paths, password } => {
|
||||||
println!("Sending {:?}", paths);
|
println!("Sending {:?}", paths);
|
||||||
send(&paths, password).await?;
|
send(paths, password).await?;
|
||||||
}
|
}
|
||||||
Commands::Receive { password } => {
|
Commands::Receive { password } => {
|
||||||
println!("Receiving password {}", password);
|
println!("Receiving password {}", password);
|
||||||
|
|
|
@ -19,6 +19,12 @@ pub struct HandshakePayload {
|
||||||
pub msg: Bytes,
|
pub msg: Bytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct EncryptedPayload {
|
||||||
|
pub nonce: Bytes,
|
||||||
|
pub body: Bytes,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum RuckError {
|
pub enum RuckError {
|
||||||
NotHandshake,
|
NotHandshake,
|
||||||
|
|
|
@ -100,8 +100,7 @@ impl<'a> Client<'a> {
|
||||||
true => {
|
true => {
|
||||||
let (tx, rx) = mpsc::unbounded_channel();
|
let (tx, rx) = mpsc::unbounded_channel();
|
||||||
tx.send(msg)?;
|
tx.send(msg)?;
|
||||||
let shared = &mut state.lock().await;
|
state.lock().await.handshakes.insert(self.id.clone(), rx);
|
||||||
shared.handshakes.insert(self.id.clone(), rx);
|
|
||||||
}
|
}
|
||||||
false => {
|
false => {
|
||||||
let shared = &mut state.lock().await;
|
let shared = &mut state.lock().await;
|
||||||
|
@ -109,6 +108,7 @@ impl<'a> Client<'a> {
|
||||||
tx.send(msg)?;
|
tx.send(msg)?;
|
||||||
}
|
}
|
||||||
if let Some(mut rx) = shared.handshakes.remove(&self.id) {
|
if let Some(mut rx) = shared.handshakes.remove(&self.id) {
|
||||||
|
drop(shared);
|
||||||
if let Some(msg) = rx.recv().await {
|
if let Some(msg) = rx.recv().await {
|
||||||
self.messages.send(msg).await?;
|
self.messages.send(msg).await?;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue