QTunnul is a secure, post-quantum ready communication library written in Go. It is designed to provide robust security against both classical and future quantum threats by utilizing state-of-the-art cryptographic primitives.
- Post-Quantum Cryptography (PQC):
- Key Exchange: Uses MLKEM-1024 (Module-Lattice-Based Key-Encapsulation Mechanism Standard) for establishing secure shared secrets.
- Authentication: Uses MLDSA-87 (Module-Lattice-Based Digital Signature Standard) for server attestation and identity verification.
- Secure Transport:
- Symmetric Encryption: Uses ChaCha20-Poly1305 (AEAD) for fast and secure data encryption.
- Hashing: Uses BLAKE3 for high-performance cryptographic hashing.
- Replay Protection:
- Implements a highly optimized sliding window Bitmap mechanism.
- Tracks a 64-packet window to efficiently detect and reject replayed or out-of-window packets.
- Correctly handles sequence number wrapping (uint64 overflow).
go get github.com/snowmerak/qtunnulThe server generates an attestation key pair and listens for client challenges.
package main
import (
"fmt"
"github.com/snowmerak/qtunnul"
)
func main() {
// 1. Generate Server Attestation Key (Long-term identity)
serverPrivKey, serverPubKey, err := qtunnul.MakeServerAttestationKey()
if err != nil {
panic(err)
}
// 2. Create a new Server Session
serverSession, err := qtunnul.NewSession(serverPrivKey)
if err != nil {
panic(err)
}
// ... Receive challenge from client ...
// response, err := serverSession.ProcessAttestationAndKeyExchange(clientChallenge)
}The client initiates the handshake by generating a challenge.
package main
import (
"fmt"
"github.com/snowmerak/qtunnul"
)
func main() {
// Assume we have the server's public key
var serverPubKey []byte = ...
// 1. Create a new Client Session
clientSession, err := qtunnul.NewClientSession(serverPubKey)
if err != nil {
panic(err)
}
// 2. Get Challenge to send to server
challenge := clientSession.GetChallenge()
// ... Send challenge to server and get response ...
// err = clientSession.ProcessServerResponse(serverResponse)
}Once the handshake is complete, both sides can send encrypted messages.
// Client sending a message
msg := []byte("Hello, Quantum World!")
encrypted, err := clientSession.Encrypt(msg)
if err != nil {
panic(err)
}
// Server receiving a message
decrypted, err := serverSession.Decrypt(encrypted)
if err != nil {
// Handle error (e.g., replay attack, decryption failure)
panic(err)
}
fmt.Printf("Received: %s\n", decrypted)- Client Hello: Client generates an MLKEM-1024 key pair and sends the encapsulation key (Challenge) to the server.
- Server Attestation:
- Server encapsulates a shared secret using the client's challenge.
- Server signs the ciphertext using its MLDSA-87 private key.
- Server sends the ciphertext and signature back to the client.
- Client Verify:
- Client verifies the server's signature using the server's known public key.
- Client decapsulates the ciphertext to recover the shared secret.
- Key Derivation: Both parties derive session keys (Send/Receive) using BLAKE3 hashing of the shared secret.
- Data Transfer: Messages are encrypted with ChaCha20-Poly1305. A sequence number (Nonce) is used for replay protection via the Bitmap filter.
- github.com/cloudflare/circl: For MLDSA (Dilithium) signatures.
- golang.org/x/crypto: For ChaCha20-Poly1305 and MLKEM (Kyber).
- lukechampine.com/blake3: For BLAKE3 hashing.
MPL-2.0 License