Package co.ankatech.ankasecure.sdk.security


package co.ankatech.ankasecure.sdk.security
The ANKASecure SDK secure-memory layer.

This package is the single sanctioned place in the SDK for handling sensitive material on the client side: cryptographic keys, passwords, JWT bearer tokens, and any byte[] or char[] that holds secrets after construction.

Public API

  • Zeroization — null-safe overwrite helpers for byte[] and char[], plus best-effort Destroyable.destroy() that swallows DestroyFailedException.
  • SecretBuffer — AutoCloseable wrapper for an owned byte[]. Zeroizes and nulls the field on SecretBuffer.close().
  • SecretChars — same pattern for char[]. Use for password / passphrase / sensitive char material.
  • BearerToken — JWT holder backed by char[] with a redacted toString() (<first6>…[REDACTED]).

What this layer CAN guarantee

  • Caller-owned byte[] returned by Cipher.doFinal(...), SecretKey.getEncoded(), etc., is overwritten with 0x00 when wrapped in SecretBuffer and closed.
  • Caller-owned char[] from System.console().readPassword() is space-filled when wrapped in SecretChars and closed.
  • char[] inside PBEKeySpec can be cleared via clearPassword().
  • Passing a Bouncy Castle 1.86 ML-KEM, ML-DSA, SLH-DSA, FrodoKEM, Classic McEliece, XMSS, XMSS^MT, LMS or HSS private key to destroyIfPossible(Object) overwrites the key's secret arrays (at least one secret array reachable from the key is all-zero after destroy(); not a claim that every internal copy is cleared).

What this layer CANNOT guarantee

  • Clearing every key object through destroy(). An EC, SM2, RSA or GOST-2012 private key completes destroy() and reports itself destroyed, but only drops its references: its secret is an immutable BigInteger that persists until collected. FALCON, HQC, BIKE, SABER, NTRU, NTRU LPRime, SMAUG-T, Ed25519, Ed448, X25519, X448, CompositePrivateKey and SecretKeySpec throw DestroyFailedException, which destroyIfPossible swallows. MLKEMPrivateKeySpec and KeyParameter do not implement Destroyable at all.
  • Bouncy Castle internal byte-array pools (released to the pool and reused without zeroization).
  • JCA scratch buffers inside Cipher.update / doFinal.
  • JIT register spills and stack-frame retention.
  • OkHttp okio.Buffer segment pool, JVM TLAB / young-gen retention, OS swap / hibernation files, native heap (BC PQC native implementations).
  • String interning and reachability — once secret material is wrapped in a String (e.g., via new String(charArray)), it cannot be reliably erased. The SDK avoids String for all sensitive material.

Build-time enforcement

Architecture rules fail the SDK build on:

  • String fields with names matching password|secret|token|jwt|bearer| clientSecret outside this package;
  • SecretKey.getEncoded() invocations outside this package not consumed inside a try-with-resources of SecretBuffer.
  • Classes
    Class
    Description
    Holder for a JWT bearer token represented as char[] rather than String, with a redacted BearerToken.toString() so accidental log statements do not leak the token verbatim.
    Mints the RFC 7523 §2.2 client assertion that proves an actor's identity with a registered key pair instead of a shared secret.
    Owning wrapper for a sensitive byte[].
    Owning wrapper for a sensitive char[] (typically passwords, passphrases, or other character-secret material returned by System.console().readPassword() or by JCA APIs that operate on char[]).
    Centralized zeroization helpers for the ANKASecure secure-memory layer.