Clavis

Clavis is a Rust library that facilitates secure, encrypted communication over asynchronous streams. Leveraging X25519 for key exchange and AES-256-GCM-SIV for encryption, Clavis ensures the confidentiality and integrity of transmitted data while providing a simple and efficient API.
Table of Contents
Installation
Add Clavis to your Cargo.toml:
[dependencies]
clavis = "0.1.0"
Alternatively, to use the latest development version:
[dependencies]
clavis = { git = "https://github.com/pyrohost/clavis.git" }
Getting Started
Define Your Packets
Clavis uses macros to define custom packet types for communication. This allows you to serialize and deserialize your data seamlessly.
First, ensure you have the necessary dependencies in your Cargo.toml:
[dependencies]
serde = { version = "1.0", features = ["derive"] }
clavis = "0.1.0"
Now, define your packet types:
use clavis::define_user_packets;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct MyData {
id: u32,
message: String,
}
define_user_packets! {
MyPacket = 1 => MyData, }
Establishing a Secure Connection
Clavis supports both client and server roles. Below are examples demonstrating how to set up each.
Client Example
use clavis::{EncryptedPacketStream, Role, Result};
use tokio::net::TcpStream;
#[tokio::main]
async fn main() -> Result<()> {
let stream = TcpStream::connect("127.0.0.1:7272").await?;
let mut encrypted_stream = EncryptedPacketStream::new(stream, Role::Client, None, None).await?;
let data = MyData {
id: 1,
message: "Hello, Server!".into(),
};
let packet = MyPacket::new(data);
encrypted_stream.write_packet(&packet).await?;
println!("Packet sent to the server.");
if let Some(response) = encrypted_stream.read_packet::<MyPacket>().await? {
println!("Received response: {:?}", response);
}
Ok(())
}
Server Example
use clavis::{EncryptedPacketStream, Role, Result};
use tokio::net::TcpListener;
#[tokio::main]
async fn main() -> Result<()> {
let listener = TcpListener::bind("127.0.0.1:7272").await?;
println!("Server listening on 127.0.0.1:7272");
loop {
let (stream, addr) = listener.accept().await?;
println!("New connection from {}", addr);
tokio::spawn(async move {
match handle_client(stream).await {
Ok(_) => println!("Connection with {} closed.", addr),
Err(e) => eprintln!("Error handling {}: {:?}", addr, e),
}
});
}
}
async fn handle_client(stream: tokio::net::TcpStream) -> Result<()> {
let mut encrypted_stream = EncryptedPacketStream::new(stream, Role::Server, None, None).await?;
if let Some(packet) = encrypted_stream.read_packet::<MyPacket>().await? {
println!("Received packet: {:?}", packet);
let response_data = MyData {
id: packet.id,
message: "Hello, Client!".into(),
};
let response_packet = MyPacket::new(response_data);
encrypted_stream.write_packet(&response_packet).await?;
println!("Response sent to client.");
}
Ok(())
}
API Documentation
Comprehensive API documentation is available here. Explore the various modules, structs, and functions to leverage the full capabilities of Clavis in your projects.
License
This project is licensed under the MIT License.