Transport-agnostic end-to-end encryption layer for secure data transfer.
foctet-core: Framing, crypto, handshake/rekey state, replay protection.foctet-http: Thin HTTP adapter forapplication/foctetbody envelopes.foctet-archive: Encrypted single-file and split archives with recipient key wrapping.foctet-transport: Layered transport integration helpers.foctet: Top-level re-export crate.
- Current releases are
0.x; breaking changes may occur while Draft v0 is finalized. - Wire-level changes must update both
SPEC.mdandtest-vectors/. - Stable wire/API compatibility is planned for
v1.
See docs/recommended-deployments.md for the recommended production composition patterns across transport E2EE, HTTP body envelopes, and archive/file delivery.
- Repository examples: examples
- Guided overview:
docs/examples.md
- Transport-agnostic encrypted framing for byte streams and split send/recv transports.
- Encrypted body envelopes for HTTP integrations such as
axumand Cloudflare Workers. - Encrypted archive formats for files and split-file delivery.
- Transport helpers for
quinn,webtrans,websock, andmuxtls.
For async stream transports, the recommended path is foctet-transport:
use foctet_core::{IdentityKeyPair, PeerIdentity, RekeyThresholds, SessionAuthConfig};
use foctet_transport::TokioTransportBuilder;
let builder = TokioTransportBuilder::new();
let channel = builder
.establish_initiator_with_auth(
stream,
RekeyThresholds::default(),
SessionAuthConfig::new()
.with_local_identity(IdentityKeyPair::generate())
.with_peer_identity(PeerIdentity::new(peer_public_key))
.require_peer_authentication(true),
)
.await?;If you already derived or exchanged Foctet session state out of band, you can still inject an active Session directly.
For encrypted files and reproducible test fixtures, foctet-archive exposes archive builders for both normal and deterministic generation:
use foctet_archive::{
ArchiveBuildSecrets, ArchiveOptions, create_archive_from_bytes_with_secrets,
};
let secrets = ArchiveBuildSecrets {
archive_id: [0x91; 16],
file_id: [0x92; 16],
dek: [0x93; 32],
wrap_ephemeral_secret_keys: vec![[0x94; 32]],
};
let (archive_bytes, meta) = create_archive_from_bytes_with_secrets(
payload,
&[recipient_public_key],
ArchiveOptions::default(),
&secrets,
)?;Use the *_with_secrets archive APIs only for reproducible vectors and deterministic tests. Production archive creation should use the default random builders.
- Foctet fails closed on sequence/key identifier exhaustion and rejects invalid all-zero X25519 shared secrets.
- Native handshake authentication supports optional Ed25519 transcript signatures with pinned peer identity verification.
- For production deployments, prefer authenticated handshakes with pinned peer keys, or bind Foctet to an already-authenticated outer channel.
- Deterministic archive secrets intentionally disable build-time randomness. Reusing them across real payloads leaks equality and key-reuse signals, so reserve them for fixtures and interoperability tests.