Created
November 18, 2025 01:43
-
-
Save williamzujkowski/bd6b6a5f983944b6ed8c9a724fc7f85f to your computer and use it in GitHub Desktop.
Zero-Knowledge Authentication Server - Python FastAPI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Zero-Knowledge Authentication Server | |
| Implements ZK-SNARK based password-less authentication | |
| """ | |
| from fastapi import FastAPI, HTTPException | |
| from pydantic import BaseModel | |
| from typing import Dict | |
| import hashlib | |
| import secrets | |
| from datetime import datetime, timedelta | |
| import jwt | |
| # Mock ZK library (replace with actual zksnark library) | |
| class ZKCircuit: | |
| def verify_proof(self, proof: bytes, public_inputs: dict) -> bool: | |
| """Verify ZK-SNARK proof without seeing password.""" | |
| # Actual implementation would use zksnark.verify_proof() | |
| # This is simplified for demonstration | |
| return True # Placeholder | |
| app = FastAPI() | |
| zk_circuit = ZKCircuit() | |
| # In-memory user database (use PostgreSQL in production) | |
| users_db: Dict[str, dict] = {} | |
| class User(BaseModel): | |
| username: str | |
| public_key: str | |
| password_hash: str | |
| class AuthRequest(BaseModel): | |
| username: str | |
| proof: bytes | |
| class RegisterRequest(BaseModel): | |
| username: str | |
| public_key: str | |
| password_hash: str | |
| @app.post("/api/register") | |
| async def register(req: RegisterRequest): | |
| """Register user with public key (password never transmitted).""" | |
| if req.username in users_db: | |
| raise HTTPException(status_code=400, detail="User exists") | |
| users_db[req.username] = { | |
| "public_key": req.public_key, | |
| "password_hash": req.password_hash, | |
| "created_at": datetime.now() | |
| } | |
| return {"status": "registered", "username": req.username} | |
| @app.get("/api/public-key/{username}") | |
| async def get_public_key(username: str): | |
| """Get user's public key for proof generation.""" | |
| if username not in users_db: | |
| raise HTTPException(status_code=404, detail="User not found") | |
| return { | |
| "username": username, | |
| "publicKey": users_db[username]["public_key"], | |
| "expectedHash": users_db[username]["password_hash"] | |
| } | |
| @app.post("/api/auth/verify") | |
| async def verify_auth(req: AuthRequest): | |
| """Verify ZK-SNARK proof (password never seen).""" | |
| if req.username not in users_db: | |
| raise HTTPException(status_code=401, detail="Invalid credentials") | |
| user = users_db[req.username] | |
| # Public inputs for proof verification | |
| public_inputs = { | |
| 'username_hash': hashlib.sha256(req.username.encode()).hexdigest(), | |
| 'expected_hash': user['password_hash'] | |
| } | |
| # Verify ZK-SNARK proof | |
| if not zk_circuit.verify_proof(req.proof, public_inputs): | |
| raise HTTPException(status_code=401, detail="Invalid proof") | |
| # Generate JWT token (standard OAuth2 flow) | |
| token_payload = { | |
| 'sub': req.username, | |
| 'exp': datetime.now() + timedelta(hours=8), | |
| 'iat': datetime.now() | |
| } | |
| token = jwt.encode(token_payload, "secret_key", algorithm="HS256") | |
| return { | |
| "access_token": token, | |
| "token_type": "bearer", | |
| "expires_in": 28800 | |
| } | |
| @app.get("/api/health") | |
| async def health(): | |
| return {"status": "healthy", "users": len(users_db)} | |
| if __name__ == "__main__": | |
| import uvicorn | |
| uvicorn.run(app, host="0.0.0.0", port=8443, ssl_certfile="cert.pem", ssl_keyfile="key.pem") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment