4个版本 (重大变更)
0.5.0 | 2023年10月14日 |
---|---|
0.4.0 | 2022年4月2日 |
0.3.0 | 2022年3月28日 |
0.2.0 | 2020年10月8日 |
0.1.0 |
|
#1160 in 加密学
被 2 crate 使用
75KB
1.5K SLoC
portal-lib
一个用于Portal的轻量级协议库 - 一个加密文件传输工具
此crate使消费者能够
- 创建/序列化/反序列化Portal请求/响应消息。
- 使用SPAKE2与对等方协商对称密钥
- 使用Chacha20-Poly1305加密文件,可以使用RustCrypto实现或Ring的
- 通过Portal中继发送/接收文件
该库分为两个抽象
- 一个高级API,通过
Portal
结构体公开,以简化传输自动化 - 一个低级API,通过
Protocol
结构体公开,如果您需要访问更底层的功能
高级API - 发送文件的示例
use 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(())
}
高级API - 接收文件的示例
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(())
}
低级API - SPAKE2密钥协商示例
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)?;
您可以使用confirm_peer()方法来验证远程对等方是否已派生与您相同的密钥,只要通信流实现了std::io::Read和std::io::Write特性。
依赖项
~3–13MB
~174K SLoC