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 facilities```rust use std::path::Path; use std::error::Error; use std::net::TcpStream; use portal_lib::{Portal, Direction, TransferInfoBuilder};
fn my_send() -> Result<(), Box
// 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(())
} ```
```rust use std::path::Path; use std::error::Error; use std::net::TcpStream; use portal_lib::{Portal, Direction, TransferInfo};
fn my_recv() -> Result<(), Box
// 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(())
} ```
```rust 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, outboundmsg) = Spake2::
// 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, &channelid, Direction::Sender, outboundmsg).unwrap();
// Derive the shared session key let key = Protocol::derive_key(state, &confirm).unwrap();
// confirm that the peer has the same key Protocol::confirmpeer(&mut stream, &channelid, 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.