Class PqcTransportInterceptor
java.lang.Object
co.ankatech.ankasecure.sdk.transport.PqcTransportInterceptor
- All Implemented Interfaces:
okhttp3.Interceptor
OkHttp Interceptor that transparently encrypts request bodies and decrypts
response bodies when PQC transport encryption is enabled.
Not wrapped, and passed through unchanged: every request while the transport is disabled, the
handshake operations (HANDSHAKE_PATH_PREFIX), /api/v3/crypto/stream/,
/api/v3/interoperability/, requests without a body (GET, DELETE, ...) and requests whose body
is duplex. Every other request is wrapped, the token grant included.
How a response is classified
application/problem+jsonon a 4xx/5xx status: a refusal the service wrote in plaintext before the transport layer could encrypt anything (session not found, undecryptable body, transport error, session store unavailable), or one a filter ahead of the transport layer wrote (401, 403, 413, 421). It is not decrypted; it is passed on unchanged, so the generated client andExceptionTranslatorsurface it as the typed SDK error carrying the problem.application/problem+jsonon any other status: refused withPqcTransportException(UNENCRYPTED_RESPONSE), unread. A refusal is never a success, so a plaintext body with a success status is exactly what a forging intermediary would send.application/octet-stream: an encrypted body, decrypted whatever its status; an encrypted 4xx/5xx reaches the caller as JSON exactly like a 2xx. An empty encrypted body is refused (UNDECRYPTABLE_RESPONSE): the services never encrypt an empty body, and an empty body carries no authentication tag to check.- Anything else, or no media type: refused with
PqcTransportException(UNENCRYPTED_RESPONSE). This includes an empty 2xx or 204 without a media type, by intent: the services skip encryption only for an empty body, and an empty unauthenticated answer cannot be told apart from a forged one. An unencrypted body is never handed to the caller as if it had been decrypted.
IOException it is (a
read timeout stays a timeout); only a body that was read in full and does not open is
UNDECRYPTABLE_RESPONSE.
A lost session is re-established once
A plaintext 400 problem whoseextensions.code is pqc.session.notfound means the server
no longer holds the session. The interceptor then evicts it (destroying its key), establishes a new one
through PqcSessionManager's single-flight replacement (concurrent requests on the same lost
session cause one handshake), re-encrypts the original body under the new key and sends it once more.
A second refusal, of any kind, is returned as the typed refusal. The decision reads the code
member only, never the localized detail. A failed handshake is an error; the request never
falls back to plaintext.-
Nested Class Summary
Nested classes/interfaces inherited from interface okhttp3.Interceptor
okhttp3.Interceptor.Chain, okhttp3.Interceptor.Companion -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringThe path prefix of the handshake operations the generatedPqcHandshakeApicalls (/init,/supported-algorithms).static final StringThe header carrying this interceptor's positive mark: set on a response only after its body was decrypted under the session key inopen(), and removed from every other response.static final StringHeader that tells the server which KEM algorithm to use.static final StringHeader that carries the PQC session identifier.static final StringHeader that indicates the payload is PQC-encrypted.Fields inherited from interface okhttp3.Interceptor
Companion -
Constructor Summary
ConstructorsConstructorDescriptionPqcTransportInterceptor(PqcTransportConfig config, PqcSessionManager sessionManager) -
Method Summary
Modifier and TypeMethodDescriptionokhttp3.Responseintercept(okhttp3.Interceptor.Chain chain) static booleanisAuthenticatedMark(String value) Whether a header value is this process's authenticated mark, compared in constant time.
-
Field Details
-
HEADER_TRANSPORT
Header that indicates the payload is PQC-encrypted.- See Also:
-
HEADER_SESSION
Header that carries the PQC session identifier.- See Also:
-
HEADER_KEM
Header that tells the server which KEM algorithm to use.- See Also:
-
HANDSHAKE_PATH_PREFIX
The path prefix of the handshake operations the generatedPqcHandshakeApicalls (/init,/supported-algorithms). They run before a session exists, so they are never wrapped: wrapping/initwould ask for the session it is creating. The prefix is the destination itself, not a setting, so the exemption cannot drift from where the handshake goes.- See Also:
-
HEADER_AUTHENTICATED
The header carrying this interceptor's positive mark: set on a response only after its body was decrypted under the session key inopen(), and removed from every other response. Its value is a random token drawn once per process (isAuthenticatedMark(String)), so a server-sent copy, with or without PQC transport, is never taken for the mark.ExceptionTranslatorturns it into the failure'sPqcRoutePolicycontext entry, the one signal that admits a fallback to the streaming route under PQC transport.- See Also:
-
-
Constructor Details
-
PqcTransportInterceptor
-
-
Method Details
-
isAuthenticatedMark
Whether a header value is this process's authenticated mark, compared in constant time.- Parameters:
value- the value ofHEADER_AUTHENTICATEDon a response, ornull- Returns:
trueonly for the value this interceptor sets after a successful decrypt
-
intercept
- Specified by:
interceptin interfaceokhttp3.Interceptor- Throws:
IOException
-