Skip to content

AnkaSecure SDK β€” Integration Flows

The SDK ships with 21 runnable reference flows that demonstrate, line by line, how to solve the most common (and a few advanced) cryptographic tasks with AnkaSecure:

  • classical β†’ post-quantum migration (re-encrypt and re-sign)
  • detached-stream processing of multi-gigabyte files
  • compact-token (JWE/JWS) operations for small payloads and API transmission
  • runtime algorithm discovery, in-memory operations, and composite hybrid keys

Each flow lives in its own Markdown file containing copy-paste-ready Java code β€” no stubs, no ellipsis.

Prerequisites

Every flow is data-plane only and operates on pre-provisioned keys and capability grants. Provision the tenant, application, actor, keys, and grants in the control plane before running any flow β€” see Before You Integrate: Control-Plane Prerequisites.


How to use the flows

  1. Choose a scenario from the table below.
  2. Click β€œView Code” to open the standalone .md that contains the full Java class (it has a main method).
  3. Compile & run with your cli.properties or adapt snippets into your project.

Need the bigger picture ? * SDK Overview β€” architecture & design goals * SDK Usage Guide β€” setup, authentication, and basic operations


The streaming request body is DUPLEX β€” and requires HTTP/2

Every streaming flow below sends its request body as a duplex stream: the SDK writes the request while it is already reading the response, rather than uploading in full and then downloading. This is not an optimisation. The server emits its response while consuming the request, so a client that waits for the upload to finish before reading deadlocks on large payloads β€” at 48 MiB the result is a stream reset in which the request write never completes at all.

On a deployed endpoint, with the same payload and the same client:

Payload Request body written Response headers arrived Outcome
48 MiB, serialized never completed β€” stream reset
48 MiB, duplex 6,326 ms 447 ms 200, 50,332,132 bytes

The response begins almost six seconds before the upload ends. That inversion is the feature β€” on a direct connection. Through Cloudflare the order changes; see Behind a buffering proxy.

Behind a buffering proxy

Some deployments are reached through Cloudflare. Cloudflare does not pass a response back to the client while an upload is still in progress, so such a deployment reads each streaming upload completely before it processes it. Your code does not change, and neither do the SDK's timeouts. The SDK's read timeout starts only once the upload has been sent, so it covers the wait for the response, not the upload: through Cloudflare, a 60-second upload completes with the default 30-second read timeout. What changes:

  • The response starts after the upload completes, rather than while it is still in progress.
  • Uploads are capped by Cloudflare's plan, and nothing on the client side raises the cap.
  • An upload that stops sending for about 15 seconds is reset.

How to recognise the cap. A larger upload is refused at once with 413, as an HTML page titled 413 Payload Too Large, not as the API's application/problem+json error β€” a 110 MiB upload is refused in a fraction of a second. Every response through Cloudflare carries server: cloudflare, so that header alone does not tell the two apart. On Cloudflare's Free and Pro plans the cap is 100 MB (Cloudflare request body limits, updated 2026-10-12 UTC).

How to recognise the reset. The SDK call fails with StreamWriteFailedException caused by a stream reset (PROTOCOL_ERROR), and no output file is written. Feed the upload from a source that keeps sending, and retry the operation.

When every streaming call is reset, the deployment is misconfigured. If each streaming call through the deployment's public hostname fails this way 15 to 18 seconds after it starts, whatever its size and while your source is still sending, retrying will not help. In that case the deployment routes Cloudflare to an entry point meant for direct clients. The StreamWriteFailedException reads "The request body was not fully written in ; nothing was committed", and a 64 MiB upload, for example, stops after about 24 MB. Splitting the data into smaller calls does not help either, because the reset follows the response, not the size. Report the failure to the operator of your deployment.

If you need larger uploads, or the response to start while the upload is still in progress, ask the operator of your deployment for an endpoint that is not reached through Cloudflare.

What this means for an integrator

HTTP/2 is required for the streaming operations, and the SDK refuses rather than downgrades. HTTP/1.1 cannot frame a duplex body. If a connection negotiates anything other than HTTP/2 β€” or if you set okhttp.http2.enabled=false β€” a streaming call fails fast with a typed Http2RequiredException, raised before a single request byte is written. It names the negotiated protocol and the requirement, and nothing else. A silent downgrade would not degrade gracefully; it would reproduce the deadlock above and surface minutes later as a reset or a read timeout with no indication of the cause.

Non-streaming calls are unaffected and work over any protocol.

A failed upload never produces an output file. The request body is written on a separate thread, so a truncated upload can coincide with a complete, well-formed response β€” and four of the eleven duplex endpoints (encrypt, sign, signThenEncrypt, encryptUtility) carry no trailing integrity verdict to catch it. (convertPkcs7 also carries no verdict, but it is the twelfth streamer and is deliberately not duplex, so it is not exposed to this failure mode.) The SDK therefore gates every promotion on the write having completed: on failure the destination is left absent, the .part quarantine file is deleted, an existing file at the destination is left byte-identical, and a typed StreamWriteFailedException carries the writer's own cause β€” its error code is IO or TIMEOUT when the upload failed on the network. When the upload stopped because the caller's own input could not be read, the SDK reports that instead, as LocalFileException naming the file. The wait is bounded, and a timeout is treated as failure, never as success.

What you must not do inside a streaming call. Nothing may touch the request body, or anything derived from it, after your call to the SDK returns control β€” the writer thread may still be using it. In particular, if you install your own OkHttp interceptor:

  • forward isDuplex() and isOneShot() if you wrap the request body β€” a wrapper that does not is transparent to the compiler and silently serializes the call;
  • never call writeTo(buffer) on the body to inspect it β€” against a duplex body that returns immediately having written nothing, and the request goes out empty or partial with no error;
  • do no work after delegating writeTo β€” no flush, no logging of the byte count.

Progress reporting (openapi.enableProgressBar=true) is duplex-aware: the final line is emitted when the body is actually closed, on the thread that wrote it.


Integration Flows Catalogue

🌊 Basic Operations - Streaming (4 flows)

For large files (GB-scale) or unlimited size operations, where the path to the API does not cap uploads (see Behind a buffering proxy).

# Flow Name Key Pattern When to Use Code
1 Asymmetric Encrypt/Decrypt (Streaming, ML-KEM-512) 🌊 Streaming GB-scale PQC encryption (ML-KEM-512) View Code
2 Detached-JWS Sign/Verify (Streaming) 🌊 Streaming Log archives, CI/CD artifact signing View Code
3 Symmetric Encrypt/Decrypt (Streaming AES-256) 🌊 Streaming Fast AES-256 for big datasets View Code
4 Asymmetric Re-encrypt (RSA β†’ ML-KEM) 🌊 Streaming RSA β†’ ML-KEM migration (zero plaintext exposure) View Code

πŸ“¦ Basic Operations - Compact (3 flows)

For small files (below the server-discovered maxPlaintextBytes, default 4 MB) or API/JSON transmission.

# Flow Name Key Pattern When to Use Code
5 ML-KEM-512 Compact Encrypt/Decrypt πŸ“¦ Compact Unit tests, microservices, small payloads View Code
6 ML-DSA-87 Compact Sign/Verify πŸ“¦ Compact Config files, JSON messages (below the configured limit) View Code
7 AES-256 Compact πŸ“¦ Compact Database secrets, tokens, credentials View Code

πŸ”„ Advanced Operations (6 flows)

For complex scenarios: re-encrypt, re-sign, nested operations.

# Flow Name Key Pattern When to Use Code
8 ML-KEM-768 β†’ ML-KEM-1024 Re-encrypt πŸ“¦ Compact Small-message PQC upgrade View Code
9 RSA-3072 β†’ ML-DSA-87 Re-sign πŸ“¦ Compact JWT/JSON signature upgrade View Code
12 Stream Re-sign (ML-DSA-65 β†’ SLH-DSA-SHA2-128S) 🌊 Streaming Large-file signature upgrade View Code
15 Compact-Token Rotation, RSA-3072 ➜ ML-KEM-768 (Re-Encrypt) πŸ“¦ Compact Bulk re-encrypt JWEs (each below the configured limit) View Code
17 Sign-Then-Encrypt Nested Operations (Compact) πŸ” Combined Authenticated encryption (JWE(JWS)) View Code
21 Sign-Then-Encrypt Nested Operations (Streaming) πŸ” Combined Large-file authenticated encryption with fail-closed integrity verdict View Code

πŸ” Discovery & Quick-Start (3 flows)

Start here if you're new to the SDK, or for runtime adaptation.

# Flow Name Key Pattern When to Use Code
13 Runtime Algorithm-Discovery Smoke-Test πŸ” Discovery Discover RECOMMENDED algorithms, run smoke tests View Code
14 In-Memory JWE/JWS Quick-start πŸ“¦ Compact 100-line reference (encrypt + sign + verify) View Code
16 Detached-JWS Stream Verification 🌊 Streaming Continuous object-storage scanning View Code

πŸ“¦ Post-Quantum Compact Operations (2 flows)

For small files (< 10 MB) with the strongest NIST-selected PQC levels.

# Flow Name Key Pattern When to Use Code
10 ML-KEM-1024 Compact Encrypt/Decrypt πŸ“¦ Compact Highest-level PQC encryption of small payloads View Code
11 ML-DSA-87 Compact Sign/Verify πŸ“¦ Compact Highest-level PQC signatures for small payloads View Code

πŸ—οΈ Composite Hybrid Keys (1 flow)

For quantum-resistant security: classical + PQC defense-in-depth.

# Flow Name Key Pattern When to Use Code
18 Composite Hybrid Keys πŸ—οΈ Composite Hybrid PQC migration aligned with NIST CSWP 39 Β§3.2.4 and the GSA PQC Buyer's Guide View Code

Composite Key Flow: This flow demonstrates quantum-resistant hybrid cryptography combining classical and post-quantum algorithms. Supports 41 validated composite pairings (27 COMPOSITE_KEM_COMBINE + 14 COMPOSITE_SIGNATURE) across NIST FIPS 203/204 and ETSI standards.


πŸ—‚οΈ PKCS#7 / CMS Migration (2 flows)

For legacy estates: inspect a PKCS#7 structure, then convert it to JOSE.

# Flow Name Key Pattern When to Use Code
19 PKCS#7/CMS Structural Analysis πŸ—‚οΈ Migration Inspect a legacy structure before converting it View Code
20 PKCS#7 ➜ JOSE Migration πŸ—‚οΈ Migration Convert SignedData / EnvelopedData to JWS / JWE View Code

Running the examples

  1. Provide credentials β€” ensure cli.properties is available or pass -Dcli.config=/path/to/cli.properties.
  2. Open the flow you’re interested in and compile the Java class.
  3. Execute β€” every class has a ready-to-run main.
  4. Inspect artefacts & console output to see keys, ciphertext, signatures, warnings, and metadata envelopes.

Need the CLI instead of Java?

The AnkaSecure Crypto CLI provides 40 commands covering all operations demonstrated in these flows and more. See the complete CLI Commands Reference for command-line usage.


Conclusion

These integration flows are production-grade blueprints that make it trivial to:

  • adopt post-quantum algorithms,
  • stream-encrypt multi-terabyte data sets,
  • rotate keys or signatures without exposing plaintext,
  • and enforce life-cycle policy in minutes rather than weeks.

For deeper dives read SDK Usage Guide and SDK Overview or contact [email protected].

Β© 2025 ANKATech Solutions Inc. β€” All rights reserved.