# django-zkp-auth

A reusable Django authentication app implementing the **Schnorr Interactive Zero-Knowledge Proof** protocol.

The user's passphrase never leaves their browser. Only a derived public key is stored on the server.

---

## How It Works

Registration and login follow the Schnorr protocol:

| Step | Party  | Action |
|------|--------|--------|
| 1    | Client | Derives private key `x = SHA256(password) % (P-1)`, computes public key `y = G^x mod P`. Sends only `y` to server. |
| 2    | Client | Picks random nonce `r`, computes commitment `t = G^r mod P`. Sends `(username, t)`. |
| 3    | Server | Generates random challenge `c`. Stores `(user_id, t, c)` in session. Returns `c`. |
| 4    | Client | Computes proof response `s = (r + c*x) % (P-1)`. Sends `s`. |
| 5    | Server | Verifies `G^s ≡ t * y^c (mod P)`. Logs user in on success. |

Security rests on the discrete logarithm problem — knowing `s`, `t`, `c`, and `y` does not reveal `x`.

---

## Installation

```bash
pip install django-zkp-auth
```

---

## Quick Start

**1. Add to `INSTALLED_APPS`:**

```python
INSTALLED_APPS = [
    ...
    'django_zkp_auth',
]
```

**2. Include the URLs in your project's `urls.py`:**

```python
from django.urls import path, include

urlpatterns = [
    path('auth/', include('django_zkp_auth.urls', namespace='django_zkp_auth')),
    ...
]
```

**3. Run migrations:**

```bash
python manage.py migrate
```

**4. Visit `/auth/register/` to create an account and `/auth/login/` to authenticate.**

---

## Configuration

All settings are optional. Add them to your `settings.py` to override defaults:

| Setting | Default | Description |
|---------|---------|-------------|
| `ZKP_PRIME_P` | `2695139` | Prime modulus `P`. Use a 2048-bit prime for production. |
| `ZKP_GENERATOR_G` | `2` | Generator `G` of the multiplicative group mod `P`. |
| `ZKP_LOGOUT_REDIRECT_URL` | `'/'` | URL to redirect to after logout. |

Example:

```python
# settings.py
ZKP_PRIME_P = 2695139          # demo value — replace for production
ZKP_GENERATOR_G = 2
ZKP_LOGOUT_REDIRECT_URL = '/home/'
```

> **Production note:** The default prime is intentionally small for readability and thesis demonstration. For a production deployment, replace it with a 2048-bit safe prime from [RFC 3526](https://www.rfc-editor.org/rfc/rfc3526) or NIST recommendations.

---

## Template Customisation

The package ships with a standalone dark-themed base template. To override any template, place your version in your project's template directory under the same namespaced path:

```
<your_project>/
└── templates/
    └── django_zkp_auth/
        ├── base.html      # override the layout/nav
        ├── login.html     # override the login page
        └── register.html  # override the registration page
```

Make sure this directory is listed in `TEMPLATES[0]['DIRS']` in your `settings.py`.

The base template exposes the following blocks:

| Block | Purpose |
|-------|---------|
| `title` | `<title>` tag content |
| `brand` | Brand name in the navbar |
| `extra_head` | Additional `<head>` content (CSS, meta tags) |
| `content` | Main page body |
| `extra_scripts` | Scripts loaded before `</body>` |

---

## Programmatic Usage

`ZKPVerifier` and `ZKPProver` are importable for tests and server-side simulations:

```python
from django_zkp_auth.zkp_utils import ZKPVerifier, ZKPProver

# Server: generate a challenge
challenge = ZKPVerifier.generate_challenge()

# Server: verify a proof
is_valid = ZKPVerifier.verify_proof(
    public_key_y=public_key,
    commitment_t=commitment,
    challenge_c=challenge,
    response_s=response,
)

# Client simulation (e.g. in tests)
private_key = ZKPProver.generate_private_key(password_hash_int)
public_key  = ZKPProver.generate_public_key(private_key)
```

---

## License

MIT
