Repository navigation
0.5.0
Added
codec-crypto — envelope encryption as a Codec<byte[]> transform. New module, first release.
Codec<Order> codec = factory.create(Order.class)
.andThen(new GzipCodec())
.andThen(EnvelopeCodec.builder(provider).build());- AES-256-GCM with a versioned, self-describing wire format; the full header is authenticated as GCM associated data.
- Pluggable key management through the
DataKeyProviderSPI — an in-process JCE provider ships (JceDataKeyProvider, AES-KW/RFC 3394 wrapped data keys); remote KMS providers (AWS KMS, Vault, GCP KMS) are implemented by consumers against the documented contract. DataKeyStrategySPI for data-key lifecycle: a fresh key per message by default (nonce-misuse-immune by construction), withBoundedDataKeyStrategyas an opt-in cache bounded by message count and age.- Decode-side key admission (
allowsKeyIdon the provider, or an explicit builder predicate) runs before any unwrap, so a KMS the application is merely permitted to use cannot be turned into a forgery oracle. - A clear error taxonomy:
DecryptionExceptionmeans the data is bad;KeyAccessExceptionmeans the key infrastructure is unavailable — never quarantine data on the latter. - Optional
java.security.Providerinjection on both builders, resolved and fail-fast checked at build time, so a FIPS-validated provider can be pinned per instance. - Zero external dependencies:
codec-cryptodepends oncodec-coreonly.
Compress-then-encrypt is the correct composition order (.andThen(gzip).andThen(crypto)); the guide documents this and the CRIME/BREACH caveat.
Documentation: Encryption guide · Threat model
Assurance
This is new cryptographic code. Before release it was measured against external references and mechanical adversaries, not only against itself:
- Known-answer tests against NIST CAVP GCM vectors and the RFC 3394 key-wrap vector, run through the production code paths.
- Jazzer fuzz targets on the decoder with a committed seed corpus (replayed in every build) and a
-Pfuzzprofile for live fuzzing; ~48M executions with no findings. - PIT mutation testing gates the build: 149/149 mutants killed, verified stable across repeated runs.
- SpotBugs with find-sec-bugs at effort Max / threshold Low, clean. One documented exclusion: the analyzer does not recognize AES key wrap as integrity-protected (RFC 3394's ICV is verified on every unwrap).
- Two adversarial design reviews and a whole-branch final review.
Not yet done: independent human review. No outside cryptographer has examined this module. The threat model page carries the checklist for one.
Known limitations — read before storing encrypted data
Straight from the threat model, in priority order:
- Ciphertext substitution between records is not defended by default. Associated data is fixed per codec instance, so under one codec and KEK an attacker with datastore write access can move record A's ciphertext into record B's row and decode succeeds. Use a distinct codec per context where rows must not be interchangeable, or bind identity inside the plaintext and verify after decode.
- AES-GCM is not key-committing. Algorithm id
0x02is reserved for a committing suite; it is not built. The single-wrapped-DEK envelope with keyId admission does not expose the multi-recipient surface that motivated key commitment elsewhere, but confirm this for your provider topology. - Random nonces under
BoundedDataKeyStrategy: up to 2^24 messages per data key (recommended 2^20). In environments that snapshot and clone VMs, duplicated RNG state can repeat a nonce under a shared cached key — prefer the defaultDirectDataKeyStrategythere, or roll on resume. - FIPS providers: the build-time probe verifies the transform name only. A provider that rejects a key or RNG at
initsurfaces on first use, not atbuild(). - Data keys are not destroyed: they live as
SecretKeySpecinstances for the lifetime of theDataKey(and the bounded cache); only the transient generation buffer is zeroed. - Timing side channels are explicitly out of scope; the uniform cryptographic-failure message covers exception content only.
Also in this release
- CI now enforces Apache 2.0 license headers on every module, including the parentless BOM.
- SonarCloud quality gate clean with zero open issues.
Requirements
- Java 25.
codec-cryptouses only JDK-provided JCE primitives (AES/GCM/NoPadding, AES/KW/NoPadding).