Package zeroecho.core.io


package zeroecho.core.io
I/O helpers for block-based transforms, passthrough processing, and tail handling.

This package provides building blocks for cryptographic I/O: chunk-transforming streams that call into a cipher, passthrough streams that compute or append trailers, a builder for configuring cipher-backed streams, a tail-stripping stream, and small I/O utilities. Components are designed to be allocation-conscious and to make finalization output (padding blocks, AEAD tags) explicit and predictable.

Key elements

  • AbstractChunkTransformInputStream - base class that reads upstream data in aligned chunks and lets subclasses implement transform(...) and doFinal(...).
  • AbstractPassthroughInputStream - forwards body bytes unchanged, invokes update(...) on each chunk, optionally emits a single trailer, then calls onCompleted() exactly once at EOF.
  • CipherTransformInputStreamBuilder - fluent builder that creates cipher-backed streams for RSA/ElGamal independent-block processing, left-zero-padded independent blocks, or continuous update+doFinal streaming.
  • SmartBlockStream, SmartPaddedBlockStream, SmartContinuousBlockStream - internal cipher-backed stream variants; the first two are restricted to independent RSA or ElGamal blocks used by the builder.
  • TailStrippingInputStream - withholds the last N bytes from the payload and delivers them to a callback at EOF (useful for tags, checksums, or footers).
  • Util - static helpers for compact length-prefix I/O, UTF-8, UUID, and packed 7-bit integers.

Typical usage

Build a streaming AES/GCM transform

javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("AES/GCM/NOPADDING");
javax.crypto.spec.GCMParameterSpec gcm = new javax.crypto.spec.GCMParameterSpec(128, ivBytes);
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, aesKey, gcm);

java.io.InputStream s = zeroecho.core.io.CipherTransformInputStreamBuilder.builder()
    .withUpstream(upstream)
    .withCipher(cipher)
    .withUpdateStreaming()          // use update(...) for bulk, doFinal() at EOF
    .withInputBlockSize(16)         // logical chunking for I/O
    .withOutputBlockSize(16)
    .withBufferedBlocks(200)        // steady-state buffering
    .withFinalizationOutputChunks(2) // room for tail bytes + 16-byte tag
    .build();

// Pipe transformed bytes
s.transferTo(out);
s.close();

Strip a fixed trailer (for example, 16-byte tag) from the end of a stream

int tagLen = 16;
zeroecho.core.io.TailStrippingInputStream in =
    new zeroecho.core.io.TailStrippingInputStream(raw, tagLen, 4096) {
        @Override
        protected void processTail(byte[] tail) throws java.io.IOException {
            // verify MAC, parse footer, etc. (do not write to 'out' here)
        }
    };

// Read payload only; the last 'tagLen' bytes are withheld and delivered to processTail(...)
byte[] payload = in.readAllBytes();
in.close(); // ensures processTail(...) runs even if not fully consumed

Design notes

  • Streams are not thread-safe; use one instance per pipeline.
  • Finalization headroom is explicit: reserve extra output chunks when a mode emits padding or tags at EOF.
  • close() implementations drain upstream as needed to guarantee trailer emission and completion hooks.
Since:
1.0