add /register endpoint for public certificate registration
Some checks failed
CI / Lint & Format (push) Failing after 15s
CI / Tests (push) Has been skipped
CI / Security Scan (push) Failing after 19s

Public endpoint allows anyone to obtain a client certificate for
authentication. Features:

- Higher PoW difficulty than paste creation (24 vs 20 bits)
- Auto-generates CA on first registration if not present
- Returns PKCS#12 bundle with cert, key, and CA
- Configurable via FLASKPASTE_REGISTER_POW

Endpoints:
- GET /register/challenge - Get registration PoW challenge
- POST /register - Register and receive PKCS#12 bundle
This commit is contained in:
Username
2025-12-21 10:34:02 +01:00
parent 68d51c5b3e
commit 5849c7406f
7 changed files with 577 additions and 10 deletions

View File

@@ -1049,3 +1049,124 @@ X-SSL-Client-SHA1: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
**Request:**
```http
GET /register/challenge HTTP/1.1
Host: localhost:5000
```
**Response (PoW disabled):**
```json
{
"enabled": false,
"difficulty": 0
}
```
**Response (PoW enabled):**
```json
{
"enabled": true,
"nonce": "a1b2c3d4e5f6a7b8a1b2c3d4e5f6a7b8",
"difficulty": 24,
"expires": 1700000300,
"token": "a1b2c3d4...:1700000300:24:signature"
}
```
**Notes:**
- Registration difficulty defaults to 24 bits (vs 20 for paste creation)
- Higher difficulty protects against automated certificate harvesting
- Configurable via `FLASKPASTE_REGISTER_POW` environment variable
---
### POST /register
Register for a client certificate (public endpoint with PoW protection).
This endpoint allows anyone to obtain a client certificate for authentication. The CA is auto-generated on first registration if it doesn't exist.
**Request (with PoW):**
```http
POST /register HTTP/1.1
Host: localhost:5000
Content-Type: application/json
X-PoW-Token: a1b2c3d4...:1700000300:24:signature
X-PoW-Solution: 12345678
```
**Request (PoW disabled):**
```http
POST /register HTTP/1.1
Host: localhost:5000
Content-Type: application/json
```
**Response (200 OK):**
```http
HTTP/1.1 200 OK
Content-Type: application/x-pkcs12
Content-Disposition: attachment; filename="client.p12"
X-Certificate-Fingerprint: b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3
<binary PKCS#12 data>
```
**Response Headers:**
| Header | Description |
|--------|-------------|
| `X-Certificate-Fingerprint` | SHA1 fingerprint for `X-SSL-Client-SHA1` header |
**PKCS#12 Bundle Contents:**
- Client certificate (signed by CA)
- Client private key (EC secp384r1)
- CA certificate (for trust chain)
**Errors:**
| Code | Description |
|------|-------------|
| 400 | Proof-of-work required (when enabled) |
| 400 | Proof-of-work failed (invalid/expired challenge) |
| 500 | PKI_CA_PASSWORD not configured |
| 500 | Certificate generation failed |
**Configuration:**
```bash
export FLASKPASTE_REGISTER_POW=24 # Registration PoW difficulty (0=disabled)
export FLASKPASTE_PKI_CA_PASSWORD="..." # Required for certificate signing
export FLASKPASTE_PKI_CERT_DAYS=365 # Client certificate validity
export FLASKPASTE_PKI_CA_DAYS=3650 # CA certificate validity (auto-generated)
```
**Using the Certificate:**
```bash
# Extract certificate and key from PKCS#12
openssl pkcs12 -in client.p12 -clcerts -nokeys -out client.crt
openssl pkcs12 -in client.p12 -nocerts -nodes -out client.key
# Use with curl
curl --cert client.crt --key client.key https://paste.example.com/
# Use fingerprint for header-based auth (behind reverse proxy)
curl -H "X-SSL-Client-SHA1: $(openssl x509 -in client.crt -fingerprint -sha1 -noout | cut -d= -f2 | tr -d :)" \
https://paste.example.com/pastes
```
**Notes:**
- `common_name` is optional; a random UUID is generated if omitted
- The PKCS#12 bundle has no password (empty password)
- CA is auto-generated on first registration if not present
- Private key is generated server-side and included in response
# Use fingerprint for header-based auth (behind reverse proxy)
curl -H "X-SSL-Client-SHA1: $(openssl x509 -in client.crt -fingerprint -sha1 -noout | cut -d= -f2 | tr -d :)" \
https://paste.example.com/pastes
```
**Notes:**
- `common_name` is optional; a random UUID is generated if omitted
- The PKCS#12 bundle has no password (empty password)
- CA is auto-generated on first registration if not present
- Private key is generated server-side and included in response