π‘οΈ PQ-BANK: Quantum-Resistant Wallet & Key Management System (Lattice Based Cryptography)

A Modern Demonstration of Module-Lattice Cryptography in Rust
A demonstration of lattice-based Post-Quantum Cryptography (PQC) β Kyber KEM for key exchange and Dilithium for signatures β combined with modern symmetric envelopes, secure wallet storage, and a tamper-proof audit chain.
Built in Rust with an eframe/egui GUI and a local server thread for realistic workflows.




β¨ Executive summary
PQ-BANK is a real-world Rust application demonstrating how to protect banking records, transaction payloads and crypto wallets against future quantum threats using lattice-based PQC (Kyber + Dilithium), AEAD envelopes (XChaCha20-Poly1305) and secure key handling patterns with a polished GUI and auditability baked in.
Table of contents
- Motivation & Value
- Architecture & Components
- Cryptography Deep-Dive (intuitive + technical)
- PQC: what & why
- Lattice-based cryptography (intuitive)
- Kyber (KEM) & Dilithium (signatures) β how we use them
- Hybrid envelope pattern (HKDF + XChaCha20-Poly1305)
- Password/wallet protection (Argon2id)
- Threat model & security considerations
- Project layout & files to include in repo
- Quickstart: build & run (copy-paste commands)
- How to test & example inputs
- Developer notes: extend to production
- FAQ / common troubleshooting
- License & contribution
Motivation & Value
Quantum computers pose a threat to common asymmetric cryptography (RSA, ECC). Organisations that handle financial or identity data must be crypto-agile and begin integrating PQC now. This project demonstrates practical engineering, showcasing how PQC primitives integrate into a secure application stack, how to combine them with symmetric primitives, and how to enhance user experience and auditability through cryptography.
Architecture & Components
Key flows:
- Wallet creation: generates Kyber + Dilithium keypairs, encrypts them with password-derived key (Argon2id + HKDF) and stores as encrypted wallet JSON.
- Transaction/file upload: client obtains server Kyber PK, encapsulates to produce ciphertext + shared secret β derives session key via HKDF β encrypts payload with XChaCha20-Poly1305 β signs payload with Dilithium β sends envelope to server.
- Server: decapsulates to session key, verifies signature, re-encrypts envelope for storage, appends signed audit block.
Cryptography deep-dive β intuitive + technical
This section explains the primitives, why they were chosen, and how theyβre applied.
1) Post-Quantum Cryptography (PQC) β what & why (intuitive)
- Traditional public-key algorithms (RSA, ECDSA) rely on number-theoretic hardness (factoring, discrete log). Quantum computers using Shorβs algorithm can break these efficiently.
- PQC algorithms are designed to resist quantum attacks. NIST standardized several PQC algorithms (Kyber, Dilithium, etc.) after an open competition.
- PQC is not a silver bullet β it requires careful composition and migration planning. This project demonstrates a safe, pragmatic composition pattern.
2) Lattice-Based Cryptography
- A lattice is a regular grid of points in high-dimensional space. Lattice problems (e.g., Learning With Errors β LWE) are hard to solve with both classical and quantum algorithms when dimensions are large and noise is present.
- Module-LWE / Module-LWR (module-lattice) are efficient variants using polynomial structures β they give strong security per key size and are the foundation of Kyber & Dilithium.
Analogy: imagine trying to find the smallest indentation in a huge, noisy multi-dimensional mattress β thatβs computationally expensive, and quantum computers donβt give an arithmetic shortcut as they do for factoring.
3) Kyber (KEM) β how itβs used
- KEM = Key Encapsulation Mechanism. Kyber is a module-lattice KEM standardized by NIST.
-
Flow (client/server):
- Server publishes Kyber public key PK_S.
- Client calls
encapsulate(PK_S) β gets (CT, shared_secret).
- Client sends CT to server.
- Server does
decapsulate(CT, SK_S) β recovers the same shared_secret.
- We derive a symmetric session key from shared_secret using HKDF-SHA256.
Why KEM? It provides forward secrecy per session and avoids classical DiffieβHellman constructs that are not quantum-safe.
4) Dilithium (Signatures) β how itβs used
Why Dilithium? It provides strong post-quantum message integrity and non-repudiation.
5) Hybrid envelope: HKDF + XChaCha20-Poly1305
We follow the envelope pattern:
shared_secret (Kyber) β session_key by HKDF(SHA256).
-
session_key (32 bytes) used with XChaCha20-Poly1305 AEAD:
- Nonce: 24 bytes (random XNonce).
- Ciphertext = AEAD.encrypt(nonce, plaintext, associated_data)
- Store
nonce||ct + metadata in encrypted envelope.
Why this approach?
- KEM gives authenticated shared secret without transmitting the secret.
- HKDF is a robust KDF that avoids raw use of shared_secret bits.
- XChaCha20-Poly1305 is fast, secure (AEAD), and simpler to use than TLS primitives. XChaChaβs 24-byte nonce reduces nonce reuse risks.
6) Password & wallet protection (Argon2id + salt)
- Wallet encryption uses a strong password KDF: Argon2id (memory-hard) with per-wallet salt and recommended parameters.
- Derived key is then passed through HKDF to finalize the symmetric key used to encrypt the wallet blob (Kyber + Dilithium private data).
- Why Argon2id: resists GPU/ASIC brute forcing and balances time/memory cost.
Threat model & security considerations
Assumptions
- Local demo: server runs on
127.0.0.1. Network exposure is off by default.
- User provides passwords only for local wallet unlocking.
Adversary capabilities considered
- Disk compromise (attacker can read encrypted wallets / envelopes).
- Network eavesdropping on local TCP (client/server messages are AEAD-encrypted β attacker sees ciphertext & Kyber CT but cannot derive shared_secret).
- Malicious file replacement (countered by Dilithium signatures & audit chain).
What this design defends
- Confidentiality: file contents & private keys encrypted at rest and in transit.
- Integrity/Authenticity: Dilithium signatures on transactions and signed audit logs.
- Forward secrecy for sessions: Kyber per-session KEM.
Limitations / what we do NOT claim
- This demo is not production-hardened: key backup, HSM/TPM integration, network TLS (mTLS/QUIC), hardened authentication, and formal audit are required for production. See Production Roadmap.
Project layout & files to include in the repo
pqbank/
ββ Cargo.toml # dependency manifest (stable versions only)
ββ README.md # this file
ββ LICENSE
ββ .gitignore
ββ src/
ββ main.rs # GUI, app lifecycle, server thread
ββ wallet.rs # wallet creation, encrypt/decrypt API
IMPORTANT: add storage/ to .gitignore. Runtime files are created under storage/ only.
Quickstart β build & run (copy-paste)
Tested on Rust 1.91.1 (MSVC toolchain on Windows recommended).
# 1. clone
git clone https://github.com/<your-username>/pqbank.git
cd pqbank
# 2. ensure Cargo.toml uses stable versions (no -rc)
# (the repo already contains a tested Cargo.toml)
# 3. clean then build
cargo clean
cargo build --release
# 4. run (GUI)
# Linux / macOS
./target/release/pqbank
# Windows (PowerShell)
.\target\release\pqbank.exe
When launched:
- GUI opens
- background server thread starts and listens on
127.0.0.1:40000
- storage directory
./storage/ is created automatically
1. Create a wallet (Wallet Manager)
- Wallet name:
demo_wallet
- Password:
Test@1234! (use dummy data for public repos)
2. Unlock the wallet
- Use the same password to decrypt; GUI shows Dilithium public key (b64) and Kyber public key (b64).
3. Send a transaction
4. Upload a sample file
5. Verify logs
- Open Audit Logs β click Verify Chain. Should report chain integrity OK and list actions.
Transaction JSON
{
"amount": 2500,
"currency": "INR",
"sender": "sumit_demo",
"receiver": "ACC5566778899",
"timestamp": "2025-12-10T14:32:12+05:30"
}
Encrypted envelope (stored on server) β conceptual
{
"id": "file-uuid",
"nonce": "<base64>",
"ciphertext": "<base64>",
"signature": "<base64>",
"signer_pubkey": "<b64>",
"meta": { "filename": "receipt.csv", "uploaded_at": "..." }
}
Developer notes β how to extend to production (roadmap for reviewers)
A recruiter reading this will want to know you understand the gaps. Suggested roadmap:
- Replace local server thread with axum/quinn server (mutual auth + QUIC).
- HSM / TPM: move server private keys into hardware keystore (TPM sealed keys or cloud KMS).
- Auth layer: OAuth2 / OpenID Connect for users; integrate CSRF/XSRF protections for web clients.
- Persistent DB: Postgres for metadata; object store for blobs (S3). Use envelope encryption; only store ciphertext.
- TLS / mTLS + hardened networking: apply DDoS protections, rate limiting, TLS cert rotation.
- CI/CD + SCA: run cargo audit, clippy, fmt, unit tests, fuzz tests.
- Third-party crypto audit + formal verification before any real funds.
- Key rotation & backup strategy + secure escrow for emergency recovery.
FAQ & Troubleshooting
Q: I see build errors on Windows related to winapi or eframe
Ans: Make sure Cargo.toml pins eframe = "0.24.1" and includes a winapi override enabling "winuser" features (the repo provides a tested Cargo.toml). Run cargo clean then cargo build.
Q: Why store server keys locally?
Ans: This is a demo. In production, use an HSM or KMS.
Q: Is this production ready?
Ans: No, it demonstrates design and implementation patterns. Production requires audits, HSMs, hardened auth and deployment.
Contributing / Code of Conduct
Contributions welcome! If you contribute:
- Add tests for any crypto/network code you change
- Keep private keys out of commits
- Follow Rustfmt and Clippy suggestions
License
MIT License β see LICENSE for full text.