ZKAC/docs/SECURITY.md
2026-04-09 18:39:36 +02:00

76 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Security model and audit notes (ZKAC 0.1)
This document summarizes the design, residual risks, and recommendations for operators integrating **ZKAC**. It is not a substitute for independent review before high-assurance deployment.
## Goals
- **Authentication:** Only holders of a valid BBS+ credential for a registered role can complete `verify_auth` for that role.
- **Confidentiality & integrity:** Session payloads are authenticated-encrypted (ChaCha20-Poly1305) with a key derived from an ephemeral X25519 handshake.
- **Replay resistance:** Duplicate ciphertexts in a direction are rejected (sliding window + monotonic counter).
- **Unlinkability (credential layer):** BBS+ presentations are intended to be unlinkable across sessions when the presentation header (here, the session transcript hash) differs; the verifier learns only the disclosed attributes (opaque `role_id`, epoch) and validity.
- **Server cannot forge credentials:** The server stores only the issuer **public** key per role; forging requires the issuer secret key.
## Cryptographic components
| Layer | Primitive | Purpose |
|-------|-----------|---------|
| Transport | X25519 ephemeral DH, HKDF-SHA256, ChaCha20-Poly1305 | Session keys, AEAD |
| Credentials | BBS+ on BLS12-381 (zkryptium), SHAKE256 ciphersuite | Blind issuance, ZK presentations |
| Role IDs | BLAKE2b-512 (truncated to 32 bytes) | Opaque role identifiers |
## Threats considered
### Network attacker (passive)
- Observes ciphertexts; cannot break ChaCha20-Poly1305 or derive session keys without breaking X25519 / HKDF under standard assumptions.
### Network attacker (active / MITM)
- **Without binding the handshake to authenticated long-term keys:** A MITM can run its own X25519 exchange with each side and decrypt/modify traffic unless an **out-of-band** binding exists (e.g. TLS with server authentication, or clients verifying server `PublicKey` through a trusted channel). The librarys `Keypair` / `PublicKey` are available for application-level identity display or future binding; **this release does not sign the handshake with long-term keys**.
- **Recommendation:** Run the protocol inside **TLS 1.3** (or similar) for production, or add an explicit long-term key signing step over the transcript if you need standalone MITM resistance.
### Malicious server
- Can **learn** opaque `role_id`, current epoch, and that *some* valid member authenticated.
- **Cannot** forge BBS+ credentials without the issuer secret key.
- **Cannot** learn `member_secret` from presentations under the BBS+ security assumptions.
- **Cannot** distinguish which specific member authenticated among valid credential holders (unlinkability holds against the verifier for distinct presentation headers).
### Malicious client
- Cannot decrypt others traffic without session keys.
- Cannot produce valid auth for a role without a valid credential + correct epoch + registry entry.
### Denial of service
- **Auth packet size:** Proof length is capped (`MAX_BBS_AUTH_PROOF_BYTES`, 256 KiB) to bound allocations.
- **Handshake:** Fixed 32-byte messages; no variable-length handshake parsing.
- General packet limits should still be enforced at the application layer (total message size, rate limits).
## Operational requirements
1. **Issuer secret key:** Protect `BbsIssuer` secret material (HSM, KMS, or encrypted at rest). Compromise = ability to issue arbitrary credentials for that role.
2. **Member storage:** `member_secret` and finalized `Credential` material must be protected; loss = re-enrollment required.
3. **Epoch revocation:** On compromise or policy change, call `set_epoch` and re-issue credentials only to legitimate members; old credentials become invalid at verification time.
4. **Registry integrity:** The servers `(role_id → public key, epoch)` mapping must be integrity-protected (trusted storage or signed updates), or attackers could swap keys or epochs.
5. **Role ID privacy:** `role_id` is a hash of the role name only if you use `role_id("myrole")`; treat role names as secrets if enumeration is a concern, or derive role IDs with an additional secret salt known to members.
## Implementation notes (audit checklist)
- [x] BBS+ proof verification uses the same header and presentation binding as proof generation (`verify_presentation` in Rust).
- [x] Session transcript is included in the presentation via `present(transcript_hash)`.
- [x] Replay protection is symmetric per direction in `Session`.
- [x] Constant-time comparisons are used where critical in transport/replay paths (`subtle` crate).
- [ ] **External:** Python bindings surface raw bytes; callers must not log secrets (`secret_key_bytes`, `member_secret`, `prover_blind`).
- [ ] **External:** Use secure randomness from the OS (library uses OS RNG for key generation paths exposed in Rust).
## Known limitations
- **No post-quantum** primitives: classical security assumptions only.
- **Epoch granularity:** Revocation is coarse (epoch bump); plan issuance and rotation policy accordingly.
- **zkryptium dependency:** Security follows the underlying crate and BLS12-381/BBS+ standards; keep dependencies updated.
## Reporting issues
Report security-sensitive findings through your projects private disclosure channel (configure `SECURITY.md` contact or GitHub security advisories when the repository is public).