pub enum ZoeChallenge {
Key(Box<KeyChallenge>),
Unknown {
discriminant: u32,
data: Vec<u8>,
},
}Expand description
Forward-compatible challenge system for connection-level authentication
The Zoe protocol uses a challenge-response handshake immediately after QUIC connection establishment to verify possession of cryptographic private keys. This happens before any service streams are created, ensuring all connections have verified credentials.
§Protocol Flow
- QUIC Connection: Client connects using ML-DSA-44 mutual TLS
- Challenge Phase: Server sends
ZoeChallengeon first bi-directional stream - Response Phase: Client responds with
ZoeChallengeResponse - Verification: Server verifies proofs and sends
ZoeChallengeResult - Service Phase: Normal service streams can now be established
§Wire Format
All challenge messages are serialized using postcard format for compact binary encoding.
§Challenge Message (Server → Client)
| Field | Type | Description |
|---------------------|-------------------|--------------------------------|
| challenge_type | u8 | Forward-compatible enum tag |
| challenge_data | Vec<u8> | Serialized challenge content |§Response Message (Client → Server)
| Field | Type | Description |
|---------------------|-------------------|--------------------------------|
| response_type | u8 | Forward-compatible enum tag |
| response_data | Vec<u8> | Serialized response content |§Result Message (Server → Client)
| Field | Type | Description |
|---------------------|-------------------|--------------------------------|
| result_type | u8 | Forward-compatible enum tag |
| result_data | Vec<u8> | Serialized result content |§Security Properties
- Replay Protection: Each challenge includes a unique nonce
- Server Binding: Signatures include server’s public key
- Time Bounds: Challenges have expiration timestamps
- Connection Scoped: Verified keys are tied to specific QUIC connections
- Forward Secrecy: New challenges generated for each connection
§Example Usage
use zoe_wire_protocol::{ZoeChallenge, ZoeChallengeResponse, KeyChallenge};
// Server sends challenge
let challenge = ZoeChallenge::Key(KeyChallenge {
nonce: generate_nonce(),
server_public_key: server_key.to_bytes().to_vec(),
expires_at: current_time() + 30,
});
// Client creates multiple key proofs
let response = ZoeChallengeResponse::Key(KeyResponse {
key_proofs: vec![
KeyProof { public_key: key1_bytes, signature: sig1_bytes },
KeyProof { public_key: key2_bytes, signature: sig2_bytes },
],
});Variants§
Key(Box<KeyChallenge>)
Multi-key ML-DSA challenge allowing clients to prove multiple private keys
This challenge type allows clients to prove possession of multiple ML-DSA private keys in a single handshake round-trip. This is useful for:
- Role-based authentication: Different keys for personal, work, admin roles
- Key rotation: Proving both old and new keys during transition periods
- Delegation: Proving keys for multiple identities or organizations
- Batch verification: Efficient verification of multiple keys at once
The client must sign (nonce || server_public_key) with each private key
they wish to prove possession of.
Unknown
Unknown challenge type for forward compatibility
Trait Implementations§
Source§impl Clone for ZoeChallenge
impl Clone for ZoeChallenge
Source§fn clone(&self) -> ZoeChallenge
fn clone(&self) -> ZoeChallenge
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more