Is there a Java equivalent to Ruby's SecureRandom.hex(...) method?

Happy with anything in JVM-land:

  • Something living inside the Java crypto APIs
  • Something provided by a 3rd party/open source library
  • Even anything written in another JVM language (Groovy/Scala/Kotlin/etc.) that can be pulled in as a compiled jar

Basically I just need the ability to generate a random 32-bit key from inside Java code (which would have the same effect if I was using this Ruby method via SecureRandom.hex(32)). Any ideas?

I did try:

// import java.security.SecureRandom
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
byte[] len = new byte[32];
System.out.println("key = " + sr.nextBytes(len));

but it spits out key = null...

  • 1
    Um, the most obvious thing to try would be JRuby, no? (Note that I use neither Ruby nor JRuby, so my intuition may be very naive on this matter.) – John Y Jan 2 at 22:16

tl;dr

Integer.toHexString(
    new SecureRandom().nextInt()
)

bd594090

JRuby

Run your Ruby code on a JVM with JRuby.

java.security.SecureRandom

Java includes SecureRandom, a cryptographically strong random number generator (RNG).

Pass the number of bits to be generated, right justified, with leading zeros.

int x = new SecureRandom().nextInt() ;

1286623117

To generate a hex string, pass that int to Integer.toHexString.

String output = Integer.toHexString( x ) ;  // And maybe call `toLowerCase` or `toUpperCase` as you desire.

4cb04f8d

Extract from UUID Version 4

A UUID is a 128-bit value designed to be used as a universally-unique identifier. Originally specified as a point in time and space, combining the current moment with a MAC address plus an arbitrary number.

Later Version 4 UUID was defined to randomly generate 122 of the 128 bits. The java.util.UUID class in Java promises to use a cryptographically-strong pseudo-random number generator.

The canonical expression of a UUID is 32 hex characters with 4 hyphens. So if take such a string, remove the hyphens, we can take hex characters at the leading end as the non-random 4 bits are in the second half of the hex string.

For your 32-bit hex value, we need 1/4 of the hex characters (1/4 of 128 bits = 32 bits), or the first 8 hex characters.

String hex = 
    java.util.UUID
    .randomUUID()
    .toString()
    .replace( "-" , "" )  // Remove hyphens, leaving only hex characters.
    .substring( 0 , 8 )   // Annoying zero-based counting. 
;

The UUID standards require the hex string to be lowercase, though many implementation violate this rule. Either way, you should make call to enforce your own choice of uppercase or lowercase hex.

String hex = 
    java.util.UUID
    .randomUUID()
    .toString()
    .replace( "-" , "" )  // Remove hyphens, leaving only hex characters.
    .substring( 0 , 8 )   // Annoying zero-based counting. 
    .toLowerCase()        // Or `toUpperCase` as you desire.
;

Use entire UUID

If your purpose is to generate distinct values as identifiers, consider using the entir universally unique identifier (UUID) value discussed above.

Version 1 UUIDs are best, but if unavailable you can fall back to using Version 4. That is good enough for many purposes.

In Java, see the UUID class.

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.