Crates.io | clatter |
lib.rs | clatter |
version | 0.1.2-alpha |
source | src |
created_at | 2024-11-09 18:25:28.203519 |
updated_at | 2024-11-10 19:46:17.594108 |
description | no_std compatible implementation of Noise protocol framework with Post-Quantum extensions |
homepage | |
repository | https://github.com/jmlepisto/clatter |
max_upload_size | |
id | 1442299 |
size | 158,647 |
⚠️ Work in progress ⚠️
no_std
compatible, pure Rust implementation of the Noise protocol framework
with support for Post Quantum (PQ) extensions as presented by
Yawning Angel, Benjamin Dowling, Andreas Hülsing, Peter Schwabe, and Fiona Johanna Weber.
Main targets of this crate are correctness, extensibility, and strict no_std
compatibility
and those come with the small drawback of more verbose user experience with some boilerplate.
If you don't need PQ functionality and are developing for a regular target, you probably are better
off using these instead:
Basis of this implementation relies heavily on the abovementioned crates and I'm extending huge thanks to the developers for their effort!
⚠️ Warning ⚠️ This library has not received any formal audit and is still in early phase
From user perspective, everything in this crate is built around three types:
NqHandshake
- Classical, non-post-quantum Noise handshakePqHandshake
- Post-quantum Noise handshakeDualLayerHandshake
- Dual layer handshake, which combines and pipes two Noise handshakesUsers will pick and instantiate the desired handshake state machine with the crypto primitives
they wish to use (supplied as generic parameters) and complete the handshake using the methods
provided by the common Handshaker
trait:
write_message(...)
- Write next handshake messageread_message(...)
- Read next handshake messageis_finished()
- Is the handshake ready?finalize()
- Move to transport stateOnce the handshake is complete, the handshake state machine can be moved to transport state
by calling .finalize()
. This finishes the handshake and the returned TransportState
can
be used for encrypting and decrypting communication with the peer. Voilà!
As already mentioned, this crate is quite verbose due to no_std
compatibility requirements,
so it's a good idea to take a look at the examples for a better view of the
handshake process.
Simplified example with the most straightforward (and most unsecure) interactive PQ handshake pattern and no handshake payload data at all:
use clatter::crypto::cipher::ChaChaPoly;
use clatter::crypto::hash::Sha512;
use clatter::crypto::kem::rust_crypto_kyber::Kyber512;
use clatter::handshakepattern::noise_pqnn;
use clatter::traits::Handshaker;
use clatter::PqHandshake;
fn main() {
let mut rng_alice = rand::thread_rng();
// Instantiate initiator handshake
let mut alice = PqHandshake::<Kyber512, Kyber512, ChaChaPoly, Sha512, _>::new(
noise_pqnn(), // Handshake pattern
&[], // Prologue data
true, // Are we the initiator
None, // Pre-shared keys..
None, // ..
None, // ..
None, // ..
&mut rng_alice, // RNG instance
).unwrap();
let mut buf_alice_send = [0u8; 4096];
let mut buf_alice_receive = [0u8; 4096];
// Write handshake message and deliver to peer
let n = alice.write_message(&[], &mut buf_alice_send).unwrap();
my_send_function(&buf_alice_send[..n]);
// Receive handshake message and process it
let n = my_receive_function(&mut buf_alice_receive);
let _ = alice.read_message(&buf_alice_receive[..n], &mut[]).unwrap();
assert!(alice.is_finished());
// Move to transport state
let mut alice = alice.finalize().unwrap();
// All done! Use .send() and .receive() on the transport state to communicate
// with the peer
let n = alice.send(b"Hello from Alice", &mut buf_alice_send).unwrap();
my_send_function(&buf_alice_send[..n]);
}