Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java SecureRandom: token entropy, encoding and comparison boundaries

Last updated: 5 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

SecureRandom produces bytes from a cryptographic random generator; a token format must preserve those bytes and define its own validation rules.

Download Java source kit

The complete program targets Java 8. Compile it as one source file; its output is checked against the lesson.

Count bytes before formatting

This fixture generates 24 bytes and encodes them with unpadded URL-safe Base64. Twenty-four bytes represent 192 bits of raw random input. That number does not prove an entire authentication scheme is secure: token storage, expiry, transmission and lookup behavior remain separate requirements.

The output check uses the decoded byte count rather than a fixed token string. Tests should never expect a particular random value or seed a production token generator merely to make a screenshot reproducible.

Do not compare the wrong representation

Encoding is reversible; it does not hash or encrypt a token. Validate the transport format before decoding and handle malformed input as rejected input. When comparing secret byte strings of an expected length, MessageDigest.isEqual is preferable to writing an early-exit byte loop.

The fixture compares a token to its own decoded bytes, which verifies a round trip only. It does not implement login, token rotation or rate limiting. A database should avoid storing bearer credentials in readable form where a lookup digest can meet the design requirements.

Working program

Java
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Base64;
public class OpaqueReceiptToken {
    public static void main(String[] args) {
        byte[] entropy = new byte[24];
        new SecureRandom().nextBytes(entropy);
        String encoded = Base64.getUrlEncoder().withoutPadding().encodeToString(entropy);
        byte[] decoded = Base64.getUrlDecoder().decode(encoded);
        System.out.println("characters=" + encoded.length());
        System.out.println("bytes=" + decoded.length);
        System.out.println(MessageDigest.isEqual(entropy, decoded));
    }
}

Output

Output
characters=32
bytes=24
true

Costs and boundaries

Generation and encoding scale with token length; this fixed fixture uses bounded buffers. Provider initialization can have different costs from later calls. Benchmark the actual generator and deployment rather than treating a tiny example as a latency guarantee.

Common Mistakes

  • Do not use Random for bearer token generation.
  • Base64 is not encryption.
  • Never log the generated credential as routine diagnostic data.

Read next

Java byte streams: partial reads and bounded copying, Java test boundaries: injected collaborators and behavior-focused checks, Password encoding.

Apply this contract in Spring

Spring PasswordEncoder: salted verification rather than reversible storage. These lessons keep framework assembly separate from the Java contract.

Extend the tested workflow

Continue with Spring Security JWT resource server: validate trust before checking scope.

Cryptographic API boundaries

Continue with Java SecureRandom token encoding: preserve unpredictable bytes in a URL-safe form, Java AES-GCM: reject a changed ciphertext before accepting plaintext.

java
secure-random-tokens
Storage details