Crates.io | portal-lib |
lib.rs | portal-lib |
version | 0.5.0 |
source | src |
created_at | 2020-10-02 18:46:48.076226 |
updated_at | 2023-10-14 23:39:01.327541 |
description | A Secure file transfer library, written in Rust. The library utilizes SPAKE2 for key negotiation over an insecure channel, and ChaCha20Poly1305 Authenticated Encryption to encrypt the file with the derived shared symmetric key. This enables two peers to transfer a file over any channel without needing to trust the intermediary relay. |
homepage | https://github.com/landhb/portal |
repository | https://github.com/landhb/portal |
max_upload_size | |
id | 295519 |
size | 84,720 |
A small Protocol Library for Portal - An encrypted file transfer utility
This crate enables a consumer to:
The library is broken up into two abstractions:
Portal
struct, to facilitate automating transfers easilyProtocol
struct, if you need access to lower-level facilitiesuse std::path::Path;
use std::error::Error;
use std::net::TcpStream;
use portal_lib::{Portal, Direction, TransferInfoBuilder};
fn my_send() -> Result<(), Box<dyn Error>> {
// Securely generate/exchange ID & Password with peer out-of-band
let id = String::from("id");
let password = String::from("password");
// Connect to the relay - the ID will be used to connect the peers
let mut portal = Portal::init(Direction::Sender, id, password)?;
let mut stream = TcpStream::connect("127.0.0.1:34254")?;
// The handshake must be performed first, otherwise
// there is no shared key to encrypt the file with
portal.handshake(&mut stream)?;
// Add any files/directories
let info = TransferInfoBuilder::new()
.add_file(Path::new("/etc/passwd"))?
.finalize();
// Optional: implement a custom callback to display how much
// has been transferred
fn progress(transferred: usize) {
println!("sent {:?} bytes", transferred);
}
// Send every file in TransferInfo
for (fullpath, metadata) in portal.outgoing(&mut stream, &info)? {
portal.send_file(&mut stream, fullpath, Some(progress))?;
}
Ok(())
}
use std::path::Path;
use std::error::Error;
use std::net::TcpStream;
use portal_lib::{Portal, Direction, TransferInfo};
fn my_recv() -> Result<(), Box<dyn Error>> {
// Securely generate/exchange ID & Password with peer out-of-band
let id = String::from("id");
let password = String::from("password");
// Connect to the relay - the ID will be used to connect the peers
let mut portal = Portal::init(Direction::Sender, id, password)?;
let mut stream = TcpStream::connect("127.0.0.1:34254")?;
// The handshake must be performed first, otherwise
// there is no shared key to encrypt the file with
portal.handshake(&mut stream)?;
// Optional: User callback to confirm/deny a transfer. If
// none is provided, this will default accept the incoming file.
// Return true to accept, false to reject the transfer.
fn confirm_download(_info: &TransferInfo) -> bool { true }
// Optional: implement a custom callback to display how much
// has been transferred
fn progress(transferred: usize) {
println!("received {:?} bytes", transferred);
}
// Decide where downloads should go
let my_downloads = Path::new("/tmp");
// Receive every file in TransferInfo
for metadata in portal.incoming(&mut stream, Some(confirm_download))? {
portal.recv_file(&mut stream, my_downloads, Some(&metadata), Some(progress))?;
}
Ok(())
}
use spake2::{Ed25519Group, Identity, Password, Spake2};
// Securely receive/derive your id & password for this session
let channel_id = String::from("myid");
let password = String::from("mysecurepassword");
// Init a Spake2 context
let (state, outbound_msg) = Spake2::<Ed25519Group>::start_symmetric(
&Password::new(&password.as_bytes()),
&Identity::new(&channel_id.as_bytes()),
);
// Connect to the relay
let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
// Send the connection message to the relay. If the relay cannot
// match us with a peer this will fail.
let confirm =
Protocol::connect(&mut stream, &channel_id, Direction::Sender, outbound_msg).unwrap();
// Derive the shared session key
let key = Protocol::derive_key(state, &confirm).unwrap();
// confirm that the peer has the same key
Protocol::confirm_peer(&mut stream, &channel_id, Direction::Sender, &key)?;
You can use the confirm_peer() method to verify that a remote peer has derived the same key as you, as long as the communication stream implements the std::io::Read and std::io::Write traits.