lib-q-hpke 0.0.5

HPKE implementation for lib-q
Documentation
# lib-q-hpke

RFC 9180–aligned Hybrid Public Key Encryption using **post-quantum-only** primitives (ML-KEM family for the HPKE KEM role in the default provider path; no classical KEM or classical signatures in that path).

## Overview

lib-q-hpke implements HPKE for the lib-q stack: protocol logic and types in this crate, with KEM/AEAD/hash work delegated through `lib-q-kem`, `lib-q-aead`, and `lib-q-hash`. The high-level [`HpkeContext`](src/lib.rs) holds a `lib_q_core::CryptoProvider` for `KemContext` **and** an `Arc<dyn HpkeCryptoProvider + Send + Sync>` (default [`PostQuantumProvider`](src/providers/post_quantum.rs)) for encapsulation, KDF, AEAD, and exporter operations. Use [`HpkeContext::with_hpke_crypto`](src/lib.rs) to swap the HPKE backend; `with_provider` only replaces the inner `KemContext` crypto. Today the default provider wires **ML-KEM only** for HPKE KEM (other PQ KEMs may exist in the workspace but are not in the `HpkeKem` catalog yet).

## Interoperability

Profiles, a mode×suite matrix, and fixture provenance are documented under the workspace [interoperability.md](../../docs/interoperability.md) and [hpke-architecture.md](../../docs/hpke-architecture.md). For code, see [`lib_q_hpke::interop`](src/interop.rs). Run the integrator-oriented example (requires `std`):

`cargo run -p lib-q-hpke --example hpke_interop_negotiation --features std`

## Supported Algorithms

### Key Encapsulation Mechanisms (KEM)
- ML-KEM-512 (Level 1 security)
- ML-KEM-768 (Level 3 security)
- ML-KEM-1024 (Level 5 security)

### Key Derivation Functions (KDF)
- HKDF-SHAKE128
- HKDF-SHAKE256
- HKDF-SHA3-256
- HKDF-SHA3-512

### Authenticated Encryption (AEAD)
- Saturnin-256 (32-byte key, 16-byte nonce, 32-byte tag)
- SHAKE256-based AEAD (16-byte tag)
- Keccak duplex-sponge AEAD via `lib-q-aead` — enable Cargo feature **`duplex-sponge-aead`** on this crate (when using the umbrella `lib-q` crate, enable **`hpke-duplex-aead`**)
- Export-only mode (`HpkeAead::Export`) for exporter-secret usage without message encryption

## Quick Start

```rust
use lib_q_core::{Algorithm, KemContext, KemPublicKey, KemSecretKey};
use lib_q_hpke::HpkeContext;
use libq::LibQCryptoProvider;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create HPKE context (umbrella `lib-q` crate, Rust name `libq`)
    let provider = Box::new(LibQCryptoProvider::new()?);
    let mut hpke_ctx = HpkeContext::with_provider(provider);
    
    // Generate key pair
    let mut kem_ctx = KemContext::with_provider(Box::new(LibQCryptoProvider::new()?));
    let keypair = kem_ctx.generate_keypair(Algorithm::MlKem512)?;
    let recipient_pk = KemPublicKey::new(keypair.public_key().as_bytes().to_vec());
    let recipient_sk = KemSecretKey::new(keypair.secret_key().as_bytes().to_vec());
    
    // Encrypt message
    let message = b"Hello, HPKE!";
    let (encapsulated_key, ciphertext) = hpke_ctx.seal(
        &recipient_pk,
        b"application-info",
        b"additional-data",
        message,
    )?;
    
    // Decrypt message
    let decrypted = hpke_ctx.open(
        &encapsulated_key,
        &recipient_sk,
        b"application-info",
        b"additional-data",
        &ciphertext,
    )?;
    
    assert_eq!(decrypted, message);
    Ok(())
}
```

## HPKE Modes

### Base Mode
Standard HPKE without additional authentication.

```rust
let mut sender_ctx = hpke_ctx.setup_sender(&recipient_pk, b"session-info")?;
let ciphertext = sender_ctx.seal(b"aad", message)?;
```

### PSK Mode
Pre-shared key authentication.

```rust
let psk = b"shared-secret-key";
let psk_id = b"psk-identifier";
let mut sender_ctx = hpke_ctx.setup_sender_psk(
    &recipient_pk,
    b"session-info",
    psk,
    psk_id,
)?;
```

### Auth Mode
Sender authentication using asymmetric keys.

```rust
let mut sender_ctx = hpke_ctx.setup_sender_auth(
    &recipient_pk,
    b"session-info",
    &sender_sk,
    &sender_pk,
)?;
```

### AuthPSK Mode
Combined PSK and sender authentication.

```rust
let mut sender_ctx = hpke_ctx.setup_sender_auth_psk(
    &recipient_pk,
    b"session-info",
    psk,
    psk_id,
    &sender_sk,
    &sender_pk,
)?;
```

### PSK / AuthPSK wire format

For PSK and AuthPSK modes, the default is [`HpkePskWireFormat::Rfc9180`](src/types.rs) (RFC 9180 on-the-wire layout). Both peers may set [`HpkePskWireFormat::LibQCommitmentSuffix`](src/types.rs) with [`HpkeContext::set_psk_wire_format`](src/lib.rs) to reject wrong `(psk, psk_id)` or a mismatched primary KEM ciphertext before decapsulation; that suffix is **not** interoperable with strict third-party RFC 9180 implementations.

## Cargo features (summary)

| Feature | Purpose |
|---------|---------|
| `std` | Standard library support |
| `alloc` | Required for normal operation (enforced by the crate) |
| `ml-kem` | ML-KEM through `lib-q-kem` (default) |
| `hash` | HKDF hash backends via `lib-q-hash` (default) |
| `saturnin` / `shake256` | AEAD algorithms (defaults) |
| `duplex-sponge-aead` | Duplex-sponge AEAD in `HpkeAead::DuplexSpongeAead` |
| `wasm` | `wasm32` bindings and helpers |
| `secure-rng` | OS-backed RNG where applicable (default) |

See [`Cargo.toml`](Cargo.toml) for the full feature matrix and optional dev dependencies.

## Documentation

- [Architecture overview](../docs/hpke-architecture.md) — workspace-level HPKE design (PQ-only path, PSK wire format, interoperability)
- [API Reference](docs/API_REFERENCE.md) — public API
- [Security Considerations](docs/SECURITY_CONSIDERATIONS.md) — security analysis and best practices
- [Architecture details](docs/ARCHITECTURE.md) — module layout and provider wiring in this crate

## Testing

The implementation includes comprehensive test coverage:

```bash
# Run all tests
cargo test

# Run specific test suites
cargo test --test psk_mode_comprehensive_tests
cargo test --test authpsk_mode_comprehensive_tests
cargo test --test security_validation_comprehensive_tests
```

## Wire sizes (KEM)

Public key and encapsulated ciphertext lengths match [`HpkeKem`](src/types.rs) (`public_key_len` / `enc_len`):

| KEM | NIST category (approx.) | Public key | Encapsulated ciphertext |
|-----|-------------------------|------------|-------------------------|
| ML-KEM-512 | 1 | 800 B | 768 B |
| ML-KEM-768 | 3 | 1184 B | 1088 B |
| ML-KEM-1024 | 5 | 1568 B | 1568 B |

AEAD ciphertext expansion is plaintext length plus the AEAD tag (e.g. 32 bytes for Saturnin-256); see `HpkeAead::tag_len` in `src/types.rs`.

## Dependencies

- `lib-q-core` - Core cryptographic types and interfaces
- `lib-q-kem` - Key encapsulation mechanism implementations
- `lib-q-hash` - Hash function implementations
- `lib-q-aead` - Authenticated encryption implementations
- `lib-q` (Rust import `libq`) — `LibQCryptoProvider` for demos; production integrations may use narrower providers

## License

This project is licensed under the same terms as the lib-q project.