Thank you for your interest in contributing to this Zero-Knowledge Proof authentication system! This project contains three language implementations (C++, Python, Rust) that maintain API compatibility.
This is a research/educational proof-of-concept implementing the Chaum-Pedersen Zero-Knowledge Proof protocol. The project has three complete implementations:
- C++ (
cpp/) - High-performance implementation - Python (
python/) - Educational and rapid prototyping implementation - Rust (
rust/) - Memory-safe, concurrent implementation
All three share:
- Identical REST API endpoints (nonce-based ZKP flow)
- Compatible SQLite database schema
- Default 2048-bit safe-prime parameters with optional 4096-bit support
- Equivalent security guarantees (replay resistance via one-time nonces)
For C++ Development:
# Ubuntu/Debian
sudo apt-get install build-essential cmake libcrypto++-dev libsqlite3-dev libcatch2-dev
# Fedora/RHEL
sudo dnf install gcc-c++ cmake cryptopp-devel sqlite-devel catch-develFor Python Development:
cd python
pip install -r requirements.txt
pip install -r requirements-dev.txt # If existsFor Rust Development:
# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Verify
rustc --version
cargo --versionC++:
cd cpp
mkdir -p build && cd build
cmake ..
make -j$(nproc)Python:
# No build needed - interpreted language
cd python
python -m pytest tests/ # Run testsRust:
cd rust
cargo build --release
cargo testWhen making changes, please maintain feature parity across all implementations:
- Implement in one language first (typically Python for prototyping)
- Add tests to verify the new functionality
- Port to other languages (C++ and Rust)
- Update documentation to reflect changes
C++ Style:
- Follow Google C++ Style Guide or project conventions
- Use meaningful variable names
- Header guards for all
.hppfiles - Document public APIs with comments
// Good
Integer computeModularExponentiation(const Integer& base, const Integer& exp, const Integer& mod);
// Not ideal
Integer cme(const Integer& a, const Integer& b, const Integer& c);Python Style:
- Follow PEP 8
- Use type hints where appropriate
- Docstrings for all public functions
def generate_proof(self, username: str, password: str, salt: str,
y1: int, y2: int) -> Proof:
"""
Generate a zero-knowledge proof for authentication.
Args:
username: The username
password: The user's password
salt: User's salt from database
y1: First public key
y2: Second public key
Returns:
Proof object containing (a1, a2, s, timestamp)
"""Rust Style:
- Follow Rust API guidelines
- Use
cargo fmtandcargo clippy - Comprehensive error handling with
Result<T, E> - Document with rustdoc comments
/// Generates a zero-knowledge proof for authentication.
///
/// # Arguments
/// * `username` - The username
/// * `password` - The user's password
/// * `salt` - User's salt from database
/// * `y1_str` - First public key (hex string)
/// * `y2_str` - Second public key (hex string)
///
/// # Returns
/// Result containing the Proof or an error message
pub fn generate_proof(&self, username: &str, password: &str,
salt: &str, y1_str: &str, y2_str: &str)
-> Result<Proof, String>All changes must include tests. We aim for high test coverage.
C++ Testing (Catch2):
TEST_CASE("ZKP valid proof verification", "[zkp]") {
ChaumPedersenZKP zkp;
auto pk = zkp.registerUser("alice", "password123");
auto proof = zkp.generateProof("alice", "password123", pk.salt, pk.y1, pk.y2);
REQUIRE(zkp.verifyProof(proof, pk.y1, pk.y2) == true);
}Python Testing (pytest):
def test_zkp_valid_proof():
zkp = ChaumPedersenZKP()
pk = zkp.register_user("alice", "password123")
proof = zkp.generate_proof("alice", "password123", pk.salt, pk.y1, pk.y2)
assert zkp.verify_proof(proof, pk.y1, pk.y2) == TrueRust Testing:
#[test]
fn test_zkp_valid_proof() {
let zkp = ChaumPedersenZKP::new();
let pk = zkp.register_user("alice", "password123").unwrap();
let proof = zkp.generate_proof("alice", "password123", &pk.salt,
&pk.y1, &pk.y2).unwrap();
assert!(zkp.verify_proof(&proof, &pk.y1, &pk.y2).unwrap());
}# C++
cd cpp/build
./test_zkp
# or
ctest --output-on-failure
# Python
cd python
pytest tests/ -v
# Rust
cd rust
cargo test -- --nocapture-
Performance Optimization
- Optimize prime generation (especially in Python)
- Benchmark and profile all implementations
- Cache parameter generation and support parameter file persistence
- Embed full RFC 3526 Group 16 (4096-bit) prime for predefined mode
-
Security Enhancements
- Add rate limiting to server endpoints
- Implement HTTPS/TLS support
- Add comprehensive input validation (size/format validation of hex bigints)
- Use Argon2id for password→x derivation (memory-hard KDF)
- Security audit and penetration testing
-
Integration Readiness
- Add comprehensive logging
- Metrics and monitoring hooks
- Database connection pooling
- Graceful shutdown handling
-
Testing
- Integration tests across implementations (wire-compatibility, canonical hex)
- Stress testing and load testing
- Property-based testing
- Edge case coverage
- C++ HTTP integration test harness (spawn server and issue requests)
-
Documentation
- Add more examples and tutorials
- Video walkthrough
- Interactive demonstrations
- Translation to other languages
-
Features
- Multi-factor authentication
- Account recovery mechanisms
- Admin interface
- Audit logging
-
Deployment
- Docker containers for each implementation
- Kubernetes manifests
- CI/CD pipelines
- Deployment guides for various platforms
-
Additional Implementations
- Go implementation
- JavaScript/TypeScript (Node.js)
- Mobile clients (iOS/Android)
-
Alternative Protocols
- Post-quantum ZKP schemes
- Other ZKP protocols (zk-SNARKs, Bulletproofs)
-
Tools
- Benchmarking suite
- Migration tools
- Database management CLI
When making changes to the API, ensure all three implementations remain compatible:
All implementations must use this exact schema:
CREATE TABLE users (
username TEXT PRIMARY KEY,
y1 TEXT NOT NULL,
y2 TEXT NOT NULL,
salt TEXT NOT NULL
);
CREATE TABLE sessions (
token TEXT PRIMARY KEY,
username TEXT NOT NULL,
created_at INTEGER NOT NULL,
expires_at INTEGER NOT NULL
);GET /params
Response: {"p":"hex","q":"hex","g":"hex","h":"hex","bits":2048,"mode":"predefined"}POST /register
Request: {"username":"alice","y1":"hex","y2":"hex","salt":"hex"}
Response: {"message":"User registered successfully","username":"alice"}POST /challenge
Request: {"username":"alice"}
Response: {"username":"alice","y1":"hex","y2":"hex","salt":"hex","nonce":"hex","expires_at":1730812345}POST /authenticate
Request: {"username":"alice","a1":"hex","a2":"hex","s":"hex","nonce":"hex"}
Response: {"message":"Authentication successful","token":"...","username":"alice"}GET /verify
Headers: Authorization: Bearer <token>
Response: {"valid": true, "message": "Session is valid"}
All large integers (y1, y2, a1, a2, etc.) must be serialized as hexadecimal strings for cross-implementation compatibility:
// C++: Crypto++ Integer to hex
std::string y1_hex;
HexEncoder encoder(new StringSink(y1_hex));
y1.Encode(encoder, y1.ByteCount());# Python: int to hex
y1_hex = hex(y1)[2:] # Remove '0x' prefix// Rust: BigUint to hex
let y1_hex = y1.to_str_radix(16);All implementations must compute the challenge as:
c = SHA-256( hex(a1) | "|" | hex(a2) | "|" | hex(y1) | "|" | hex(y2) | "|" | nonce ) mod q
where hex(·) is lowercase hex without 0x prefix, and nonce is the server-provided one-time value.
When adding features or making significant changes:
-
Update relevant README files
- Main
README.md - Implementation-specific READMEs (
cpp/README.md,python/README.md,rust/README.md)
- Main
-
Update theory docs if changing cryptography
docs/ZKP_THEORY.mddocs/CHAUM_PEDERSEN.mddocs/IMPLEMENTATION.md
-
Update API documentation
docs/API.md
-
Update visual guide for major changes
docs/VISUAL_GUIDE.md
-
Keep documentation index current
docs/INDEX.md
-
Fork the repository (when applicable)
-
Create a feature branch
git checkout -b feature/your-feature-name
-
Make your changes
- Follow code style guidelines
- Add tests
- Update documentation
-
Test thoroughly
# Test all implementations cd cpp/build && ./test_zkp cd ../../python && pytest tests/ cd ../rust && cargo test
-
Commit with clear messages
git commit -m "Add feature: description of what you added" -
Ensure all implementations work together
- Test cross-implementation compatibility
- Verify database schema compatibility
- Test API endpoints with different client/server combinations
-
Submit pull request with:
- Clear description of changes
- Motivation/rationale
- Testing performed
- Documentation updates included
- Breaking changes noted (if any)
# Build with debug symbols
cd cpp/build
cmake -DCMAKE_BUILD_TYPE=Debug ..
make
# Use gdb
gdb ./auth_server# Add breakpoints
import pdb; pdb.set_trace()
# Or use pytest with pdb
pytest tests/ --pdb# Build with debug info (default for cargo build)
cargo build
# Use rust-gdb or rust-lldb
rust-gdb target/debug/zkp-serverSolution: This is expected. Python's sympy prime generation takes 30–60 seconds for 2048-bit safe primes and can be significantly longer for 4096-bit. Consider:
- Using predefined parameters (recommended for 2048-bit)
- Implementing Miller–Rabin in a C extension
- Using PyPy instead of CPython
- Caching generated parameters to disk and loading at startup
Solution: SQLite doesn't handle high-concurrency writes well. For integrations:
- Use connection pooling
- Consider PostgreSQL or MySQL
- Implement retry logic with exponential backoff
Solution:
- Use
cargo checkfor fast feedback - Enable incremental compilation (usually default)
- Use
sccachefor caching compiled dependencies
Solution:
# Find process using port
lsof -i :8080
# Use different port
./auth_server --port 9000
python main.py --port 9000
cargo run --bin zkp-server -- --port 9000When contributing, please keep in mind:
- Never commit secrets - No API keys, passwords, or private keys
- Validate all inputs - Especially user-provided data
- No SQL injection - Use parameterized queries
- Timing attacks - Use constant-time comparisons for sensitive data
- Random number generation - Use cryptographically secure RNGs
- Dependency updates - Keep crypto libraries updated
This is a research/educational project. Please:
- Be respectful and constructive
- Focus on code quality and security
- Help others learn
- Credit sources and references
- Follow responsible disclosure for security issues
- Check existing documentation in
docs/ - Review
README.mdfor project overview - See
QUICKSTART.mdfor getting started - Read
IMPLEMENTATION.mdfor implementation details
This project is a proof-of-concept for research and educational purposes. Please review the license before contributing.
This project implements:
- Chaum-Pedersen Protocol - Chaum & Pedersen (1992)
- Fiat-Shamir Transform - Fiat & Shamir (1986)
- Schnorr Protocol foundations - Schnorr (1991)
Thank you for contributing to ZKP education and research! 🚀