Quill is a peer-to-peer messenger built in C++23 that is fully resistant to quantum computer attacks. It implements the NIST post-quantum standards (FIPS 203, FIPS 204) for key exchange and digital signatures, combined with AES-256-GCM for session encryption.
Built as a semester project at AGH University of Science and Technology, KrakΓ³w.
Foundation for an upcoming engineering thesis on intelligent PQC algorithm selection.
Classical asymmetric cryptography (RSA, ECDH) is theoretically broken by Shor's algorithm running on a sufficiently large quantum computer. In 2024, NIST published the first quantum-resistant standards. Quill implements them from scratch β no TLS, no OpenSSL handshake, custom protocol.
Classical crypto Post-quantum (Quill)
βββββββββββββββββ ββββββββββββββββββββββ
RSA-2048 β broken Kyber-768 β FIPS 203 β
ECDH β broken Dilithium β FIPS 204 β
AES-256-GCM β safe* AES-256-GCM β session β
* Grover's algorithm reduces AES-256 to ~128-bit security β still safe.
Quill implements a custom 4-step handshake. There is no classical asymmetric crypto anywhere in the stack.
ALICE BOB
β β
βββββ β ClientHello βββββββββββββββββββββββββΊβ
β security level, supported algos, β
β Alice's Dilithium public key β
β β generates Kyber keypair
β β signs pub_kyber with Dilithium
βββββ β‘ ServerHello ββββββββββββββββββββββββ β
β pub_kyber_B, pub_dil_B, β
β sig_B(pub_kyber_B) β
β β
β verify sig_B β β
β Kyber encaps(pub_kyber_B) β
β β (ciphertext, shared_secret) β
β β
βββββ β’ ClientKeyExchange βββββββββββββββββββΊβ
β ciphertext, sig_A(ciphertext) β
β β verify sig_A β
β β Kyber decaps β shared_secret
βββββ β£ ServerFinished βββββββββββββββββββββ β
β sig_B(hash(shared_secret)) β
β β
β key = HKDF(shared_secret) β key = HKDF(shared_secret)
β β
βββββββββ AES-256-GCM encrypted session ββββββ
β nonce(12B) β ciphertext β GCM tag(16B) β
Security properties:
| Property | Mechanism |
|---|---|
| Quantum-safe key exchange | Kyber-768 (ML-KEM, FIPS 203) |
| Mutual authentication | Dilithium (ML-DSA, FIPS 204) |
| MITM protection | Dilithium signatures + TOFU known_hosts (block on key change) |
| Forward secrecy | New Kyber keypair per session |
| Session encryption | AES-256-GCM |
| Key derivation | HKDF-SHA256, salt = handshake transcript |
| Nonce safety | 96-bit random nonce per message |
| Replay protection | Per-direction sequence numbers bound via GCM AAD (CHAT|<seq>); receiver rejects seq β€ last (fail-closed), reset on PFS rotation |
Quill supports three configurable security levels, selectable at connection time:
| Level | KEM | Signature | NIST Level | Use case |
|---|---|---|---|---|
FAST |
Kyber-512 | FALCON-512 | 1 (~AES-128) | IoT, real-time |
BALANCED |
Kyber-768 | ML-DSA-65 (Dilithium) | 3 (~AES-192) | default |
MAX |
Kyber-1024 | ML-DSA-87 (Dilithium) | 5 (~AES-256) | critical data |
# Arch Linux
sudo pacman -S cmake openssl
# Ubuntu/Debian (OpenSSL < 3.2 wymaga libargon2 dla szyfrowania profili)
sudo apt install cmake libssl-dev libargon2-devliboqs must be built from source:
git clone https://github.com/open-quantum-safe/liboqs
cd liboqs && mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
sudo cmake --install .git clone --recurse-submodules https://github.com/Smitchelld/Quill.git
cd Quill
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)If you already cloned without submodules:
git submodule update --init --recursiveRequires Google Test (pacman -S gtest / apt install libgtest-dev):
cd build && ./quill_testsQuill ships as a single ImGui application β each instance can host (server) or connect (client):
./QuillStart one instance in Server mode, then connect another in Client mode (host, port, security level configurable in the setup panel). The PQC handshake runs automatically; after the secure tunnel is established, all messages and file transfers are AES-256-GCM encrypted.
quill/
βββ src/
β βββ crypto/ # CryptoManager, KyberKEM, DilithiumSign, AesGcm, Hkdf,
β β # Argon2, IdentityManager, ProfileManager, TrustStore
β βββ network/ # Socket, NetworkServer, NetworkClient (TCP, length-prefixed framing)
β βββ protocol/ # MessageFormat (JSON), FileTransfer (chunking + SHA-3)
β βββ frontend/ # ImGui ChatApp, rendering, Theme
βββ tests/ # Google Test suite (97 tests), linked against quill_core
βββ third_party/ # ImGui (git submodule), portable-file-dialogs
βββ .github/workflows/ # CI: build + ctest (headless)
βββ docs/ # OVERVIEW.md β stan projektu (PL)
βββ main.cpp # GLFW/OpenGL3 + ImGui entry point
βββ CMakeLists.txt
βββββββββββββββββββββββββββββββββββββββββββββββ
β Application layer β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β AES-256-GCM (OpenSSL EVP) β session encryption
ββββββββββββββββββββββ¬βββββββββββββββββββββββββ€
β Kyber-768 KEM β Dilithium DSA β liboqs
β (ML-KEM FIPS203) β (ML-DSA FIPS204) β
ββββββββββββββββββββββ΄βββββββββββββββββββββββββ€
β HKDF-SHA256 (OpenSSL EVP_KDF) β key derivation
βββββββββββββββββββββββββββββββββββββββββββββββ€
β TCP (POSIX sockets) β transport
βββββββββββββββββββββββββββββββββββββββββββββββ
Libraries:
- liboqs β Open Quantum Safe, MIT license β Kyber, Dilithium, FALCON, SPHINCS+
- OpenSSL β Apache 2.0 β AES-256-GCM, HKDF, SHA-3, RAND_bytes; Argon2id (β₯3.2)
- libargon2 β fallback Argon2id when OpenSSL < 3.2 (e.g. Ubuntu CI)
- nlohmann/json β MIT β message serialization
- No PKI β trust is TOFU-based (like SSH/Signal): the first connection stores the peer key, fingerprints must be compared out-of-band to reach VERIFIED. There is no certificate authority β intentional for scope.
- Passphrase strength is the only offline defense β identity keys are encrypted at rest with Argon2id + AES-256-GCM, but an attacker with the key file mounts an offline attack; there is deliberately no retry lockout (it would be security theater). New profiles require a passphrase of at least 8 characters (repeated single-character strings rejected); legacy profiles can still be unlocked with their original passphrase.
- Server-relayed, not end-to-end β the server is a trusted relay: it decrypts each message from the sender and re-encrypts it per recipient under that link's session key. Every hop is AES-256-GCM, but the server sees plaintext. This is an intentional hub-and-spoke design; true E2E would require a separate per-recipient key agreement.
- NAT traversal β direct TCP, no STUN/TURN. Both peers must be reachable at a known address.
- Kyber-768 key exchange over TCP
- AES-256-GCM encrypted messaging
- Dilithium signature verification (MITM protection)
- FAST / BALANCED / MAX security levels (FALCON-512, ML-DSA-65/87)
- Multi-client with
std::thread - Rooms/channels with message isolation
- Perfect Forward Secrecy β on-the-fly key rotation
- Handshake visualizer with per-step timing, benchmarks, security dashboard
- File transfer (64KB chunks, AES-GCM per chunk, SHA-3-256 integrity)
- HKDF-SHA256 key derivation with handshake-transcript binding
- Unified
CryptoManager(handshake + TOFU + HKDF + identity, UI-free) - Persistent identity keys (0600, self-test on load) + SHA-3 fingerprints
- Local profiles with login β at-rest key encryption (Argon2id + AES-256-GCM)
- TOFU (known_hosts per profile, UNVERIFIED/KNOWN/VERIFIED, fail-closed block on key change)
- Replay protection for chat β per-direction sequence numbers bound via GCM AAD (fail-closed)
- Google Test suite β 97 tests (RFC vectors, tamper + AAD/replay, TOFU attacks, file transfer NACK + chunk_hash, socketpair handshake)
- GitHub Actions CI (headless build + ctest)
- Argon2 dual backend (OpenSSL β₯3.2 or libargon2)
- File transfer: selective repeat retransmission (FILE_NACK)
- File transfer: per-chunk SHA-3 (early integrity check before buffering)
- NAT traversal (UDP hole punching + rendezvous server)
- Engineering thesis: intelligent PQC algorithm selection
- FIPS 203 β ML-KEM (Kyber)
- FIPS 204 β ML-DSA (Dilithium)
- FIPS 205 β SLH-DSA (SPHINCS+)
- CRYSTALS-Kyber: A CCA-Secure Module-Lattice-Based KEM β Bos et al.
- CRYSTALS-Dilithium: A Lattice-Based Digital Signature Scheme β Ducas et al.
- Open Quantum Safe β liboqs documentation
AGH University of Science and Technology, KrakΓ³w
Computer Science and Intelligent Systems
Studio Projektowe β Semester 6