Class SecretValue

java.lang.Object
com.svenruppert.jsentinel.credential.secret.SecretValue
All Implemented Interfaces:
AutoCloseable

public final class SecretValue extends Object implements AutoCloseable
Short-lived container for password / pepper / token material.

Lifecycle

SecretValue is AutoCloseable so callers can scope a secret to a try-with-resources block. The close() hook calls destroy(), which overwrites the internal char[] with zeros. Once destroyed, every accessor throws IllegalStateException (CWE-226).

JVM memory honesty

The JVM offers no perfect way to scrub heap memory: garbage collection may have copied the backing array to other regions before destruction; strings produced by an unrelated caller may keep a copy elsewhere. SecretValue provides best-effort defence: it owns the backing array, never converts to String internally, and zeros temporary UTF-8 buffers it constructs. Callers should still keep secret lifetimes as short as possible.

Interoperability

Phase 1a/1b providers accept char[] for historical reasons. asChars() returns a defensive copy the caller owns; they remain responsible for zeroing it after use. The package also exposes asUtf8Bytes() for providers that need a byte[] (bcrypt, scrypt). Both methods refuse access after destruction.

  • Method Details

    • ofChars

      public static SecretValue ofChars(char[] source)
      Builds a SecretValue from a caller-owned char[]. The caller's array is defensively copied; the original array remains the caller's responsibility (and is typically zeroed immediately afterwards).
    • ofString

      public static SecretValue ofString(String source)
      Convenience overload for String inputs. Note that String instances are immutable and may be retained by the JVM string pool; prefer ofChars(char[]) for genuinely sensitive material.
    • length

      public int length()
      Number of characters held. Reported even after destruction so callers can debug lifecycle issues without recovering the value.
    • isDestroyed

      public boolean isDestroyed()
      Whether destroy() has been called.
    • asChars

      public char[] asChars()
      Returns a defensive copy of the held characters. The caller owns the returned array and should zero it after use.
      Throws:
      IllegalStateException - if the secret was already destroyed
    • asUtf8Bytes

      public byte[] asUtf8Bytes()
      Returns the UTF-8 encoding of the held characters in a fresh byte array. The internal CharBuffer and intermediate ByteBuffer backing array are zeroed before returning.
      Throws:
      IllegalStateException - if the secret was already destroyed
    • destroy

      public void destroy()
      Zeros the internal storage. Subsequent accessor calls throw IllegalStateException. Calling destroy on an already-destroyed secret is a no-op.
    • close

      public void close()
      Alias for destroy() so SecretValue can be used in try-with-resources blocks.
      Specified by:
      close in interface AutoCloseable
    • toString

      public String toString()
      Returns a redacted shape: "SecretValue[length=N, destroyed=false]". Never contains the held material (CWE-209 / CWE-312).
      Overrides:
      toString in class Object