pub struct Interceptor {
pub key_store: Arc<RwLock<KeyStore>>,
pub handshake_store: HandshakeStore,
pub replay_store: Option<ConnectionManager>,
pub memory_replay_store: Option<Arc<MemoryReplayStore>>,
pub max_body_bytes: usize,
pub max_decompressed_bytes: usize,
pub allow_encrypted_get: bool,
}Expand description
Actix-web middleware that transparently decrypts incoming request bodies and encrypts outgoing response bodies using the X25519 ECDH + AES-256-GCM + HMAC-SHA256 pipeline.
§Usage
Prefer Interceptor::new_with_memory_replay for new deployments — it enables in-memory
replay protection and sensible body/decompression size limits without requiring Redis:
use alterion_encrypt::interceptor::Interceptor;
use alterion_encrypt::{init_key_store, init_handshake_store, start_rotation};
let store = init_key_store(3600);
let hs = init_handshake_store();
start_rotation(store.clone(), 3600, hs.clone());
// App::new().wrap(Interceptor::new_with_memory_replay(store, hs))To tune size limits or add Redis replay protection after construction:
let mut interceptor = Interceptor::new_with_memory_replay(store, hs);
interceptor.max_body_bytes = 5 * 1024 * 1024; // 5 MiB raw body
interceptor.max_decompressed_bytes = 50 * 1024 * 1024; // 50 MiB decompressed
// interceptor.replay_store = Some(redis_connection_manager);Request path (POST / PUT / PATCH, and GET when allow_encrypted_get is true):
- Collect raw body bytes up to
max_body_bytes— reject 413 if exceeded. - MessagePack-decode a
Requestand validate timestamp. - Check the replay store (Redis → in-memory fallback). Fails closed on store error.
- ECDH → wrap key → AES-GCM unwrap
enc_key→ AES-256-GCM decrypt payload. - Preflight decompress against
max_decompressed_bytes— reject 413 if exceeded. - Inject
DecryptedBodyandRequestSessionKeysinto request extensions.
Requests whose body is not a valid encrypted Request are passed through unchanged.
Response path (only when RequestSessionKeys is present):
JSON → deflate → msgpack → AES-256-GCM → HMAC-SHA256 → Response → msgpack.
Fields§
§key_store: Arc<RwLock<KeyStore>>§handshake_store: HandshakeStore§replay_store: Option<ConnectionManager>Redis-backed replay store. Takes precedence over memory_replay_store when Some.
memory_replay_store: Option<Arc<MemoryReplayStore>>In-memory replay store used when replay_store is None.
Initialized automatically by Interceptor::new_with_memory_replay.
max_body_bytes: usizeMaximum raw (compressed + encrypted) request body in bytes. Requests exceeding this are
rejected with 413 before any decryption occurs. Default: DEFAULT_MAX_BODY_BYTES (1 MiB).
max_decompressed_bytes: usizeMaximum decompressed payload size in bytes. Requests whose payload would expand beyond this
are rejected with 413 after decryption but before the handler sees the body. Set this to
whatever your largest valid request body is — there is no upper bound imposed by the library.
Default: MAX_DECOMPRESSED_SIZE (10 MiB).
allow_encrypted_get: boolWhen true, GET requests that carry a body are processed through the full encrypt/decrypt
pipeline identically to POST/PUT/PATCH. The client sends the msgpack-encoded [Request]
as the GET body using the same buildRequestPacket function. Default: false.
Implementations§
Source§impl Interceptor
impl Interceptor
Sourcepub fn new_with_memory_replay(
key_store: Arc<RwLock<KeyStore>>,
handshake_store: HandshakeStore,
) -> Self
pub fn new_with_memory_replay( key_store: Arc<RwLock<KeyStore>>, handshake_store: HandshakeStore, ) -> Self
Creates an Interceptor with in-memory replay protection and default size limits
(1 MiB raw body, 10 MiB decompressed).
This is the recommended constructor for new deployments. Tune max_body_bytes and
max_decompressed_bytes on the returned value for your workload, or assign replay_store
to upgrade to Redis-backed replay detection for multi-instance deployments.
Trait Implementations§
Source§impl<S, B> Transform<S, ServiceRequest> for Interceptorwhere
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
B: MessageBody + 'static,
impl<S, B> Transform<S, ServiceRequest> for Interceptorwhere
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
B: MessageBody + 'static,
Source§type Response = ServiceResponse<EitherBody<B>>
type Response = ServiceResponse<EitherBody<B>>
Source§type Transform = InterceptorService<S>
type Transform = InterceptorService<S>
TransformService value created by this factory