| Crates.io | hightower-wireguard |
| lib.rs | hightower-wireguard |
| version | 0.2.1 |
| created_at | 2025-10-01 18:14:54.202323+00 |
| updated_at | 2025-10-11 22:32:50.365077+00 |
| description | A WireGuard Noise_IK handshake implementation |
| homepage | |
| repository | https://github.com/chrishayen/hightower-wireguard |
| max_upload_size | |
| id | 1863171 |
| size | 225,242 |
A Rust implementation of the WireGuard cryptographic handshake protocol (Noise_IK).
This crate implements the core cryptographic handshake protocol used by WireGuard. It provides the building blocks for establishing secure sessions between peers using the Noise_IK pattern with pre-shared key support.
This is not a complete VPN implementation. The following components are not included:
This library is suitable for:
Add to your Cargo.toml:
[dependencies]
# For handshake protocol only
hightower-wireguard = "0.2.1"
# For transport layer (UDP Connection and Stream)
hightower-wireguard = { version = "0.2.1", features = ["transport"] }
use hightower_wireguard::protocol::{WireGuardProtocol, PeerInfo};
use hightower_wireguard::crypto::dh_generate;
// Generate keys for both peers
let (alice_private, alice_public) = dh_generate();
let (bob_private, bob_public) = dh_generate();
// Create protocol instances
let mut alice = WireGuardProtocol::new(Some(alice_private));
let mut bob = WireGuardProtocol::new(Some(bob_private));
// Configure peers
alice.add_peer(PeerInfo {
public_key: bob_public,
preshared_key: None,
endpoint: None,
allowed_ips: Vec::new(),
persistent_keepalive: None,
});
bob.add_peer(PeerInfo {
public_key: alice_public,
preshared_key: None,
endpoint: None,
allowed_ips: Vec::new(),
persistent_keepalive: None,
});
// Perform handshake
let initiation = alice.initiate_handshake(&bob_public)?;
let response = bob.process_initiation(&initiation)?;
let peer_key = alice.process_response(&response)?;
// Now both sides have active sessions with transport keys
let alice_session = alice.get_session(response.sender).unwrap();
let bob_session = bob.get_session(response.sender).unwrap();
// Use session keys for encryption/decryption
// alice_session.keys.send_key and alice_session.keys.recv_key
let psk = [42u8; 32]; // Your pre-shared key
alice.add_peer(PeerInfo {
public_key: bob_public,
preshared_key: Some(psk),
// ... other fields
});
bob.add_peer(PeerInfo {
public_key: alice_public,
preshared_key: Some(psk),
// ... other fields
});
// Handshake will now use PSK for additional security
Messages can be serialized to and from wire format for network transmission:
use hightower_wireguard::messages::HandshakeInitiation;
// After creating a handshake initiation message
let initiation = alice.initiate_handshake(&bob_public)?;
// Serialize to wire format (148 bytes)
let bytes = initiation.to_bytes()?;
// Send over network...
// let socket.send_to(&bytes, peer_addr)?;
// On the receiving side, deserialize from bytes
let received = HandshakeInitiation::from_bytes(&bytes)?;
let response = bob.process_initiation(&received)?;
// Serialize the response (92 bytes)
let response_bytes = response.to_bytes()?;
The following message types support serialization:
HandshakeInitiation: 148 bytesHandshakeResponse: 92 bytesTransportData: 16 bytes + variable packet lengthWith the transport feature enabled, you can use the high-level UDP-based transport layer:
use hightower_wireguard::crypto::dh_generate;
use hightower_wireguard::connection::Connection;
#[tokio::main]
async fn main() {
// Generate keys
let (alice_private, alice_public) = dh_generate();
let (bob_private, bob_public) = dh_generate();
// Create connections
let alice = Connection::new("127.0.0.1:0".parse().unwrap(), alice_private)
.await
.unwrap();
let bob = Connection::new("127.0.0.1:0".parse().unwrap(), bob_private)
.await
.unwrap();
let alice_addr = alice.local_addr();
let bob_addr = bob.local_addr();
// Add peers
alice.add_peer(bob_public, Some(bob_addr)).await.unwrap();
bob.add_peer(alice_public, Some(alice_addr)).await.unwrap();
// Bob listens for incoming connections
let mut bob_incoming = bob.listen().await.unwrap();
// Alice connects to Bob
let mut alice_stream = alice.connect(bob_addr, bob_public).await.unwrap();
// Bob accepts the connection
let mut bob_stream = bob_incoming.recv().await.unwrap();
// Send and receive data
alice_stream.send(b"Hello from Alice!").await.unwrap();
let received = bob_stream.recv().await.unwrap();
println!("Bob received: {}", String::from_utf8_lossy(&received));
}
Configure persistent keep-alive to maintain NAT mappings and detect dead peers:
// Add peer with keep-alive packets sent every 25 seconds
alice.add_peer_with_keepalive(
bob_public,
Some(bob_addr),
Some(25) // send keep-alive every 25 seconds
).await.unwrap();
The transport layer provides:
Run the test suite:
# Test handshake protocol only
cargo test
# Test with transport layer
cargo test --features transport