SecureRandom produces bytes from a cryptographic random generator; a token format must preserve those bytes and define its own validation rules.
Java SecureRandom: token entropy, encoding and comparison boundaries
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
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
characters=32
bytes=24
trueCosts 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.
