Mafuba
Mafuba

Reputation: 613

Base32 encode UUID in Java

What is the most time efficient way to create and Base32 encode a random UUID in Java? I would like to use Base32 encoding to store globally unique IDs that are usable in URLs.

Upvotes: 5

Views: 8069

Answers (3)

fabiolimace
fabiolimace

Reputation: 1197

The codec Base32Codec can encode UUIDs efficiently to base-32.

// Returns a base-32 string
// uuid::: 01234567-89AB-4DEF-A123-456789ABCDEF
// base32: aerukz4jvng67ijdivtytk6n54
String string = Base32Codec.INSTANCE.encode(uuid);

There are codecs for other encodings in the same package of uuid-creator.


Disclaimer: I'm the main contributor of uuid-creator.

Upvotes: 1

Chayne P. S.
Chayne P. S.

Reputation: 1638

I agreed with the discussion that Base64Url might be more suitable but I also see the benefit of generating unique value in Base32. It's case insensitive that is easier to handle if human is involved.

This is my code to convert UUID to Base32 using Guava's BaseEncoding.

    public static String toBase32(UUID uuid){
        ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
        bb.putLong(uuid.getMostSignificantBits());
        bb.putLong(uuid.getLeastSignificantBits());
        return BaseEncoding.base32().omitPadding().encode(bb.array());
    }

Upvotes: 1

Glenn Lane
Glenn Lane

Reputation: 4010

Base32 still pads with the = character, so you'll need to do something with that if you really want to avoid URL escaping.

If you really want to avoid Base16, I recommend you use Base64 instead of Base32. If you want to use an RFC standard, try base64url. However, that standard also uses "=" for the trailing padding, so you need to escape that. It's substitutions are:

  • + -> -
  • / -> _
  • = -> =

Personally, I use a variant called Y64. It's substitutions are:

  • + -> .
  • / -> _
  • = -> -

It's not an RFC standard, but at least you don't have to worry about escaping the trailing "=".

Apache Commons Codec provides both Base64 and Base32. Here's an example with Base64 with the Y64 variant

To encode:

UUID uuid = UUID.randomUUID();
ByteBuffer uuidBuffer = ByteBuffer.allocate(16);
LongBuffer longBuffer = uuidBuffer.asLongBuffer();
longBuffer.put(uuid.getMostSignificantBits());
longBuffer.put(uuid.getLeastSignificantBits());
String encoded = new String(Base64.encode(uuidBuffer.array()), 
        Charset.forName("US-ASCII"));
encoded = encoded.replace('+', '.')
        .replace('/', '_')
        .replace('=', '-');

And decode:

String encoded; // from your request parameters or whatever
encoded = encoded.replace('.', '+')
        .replace('_', '/')
        .replace('-', '=');
ByteBuffer uuidBuffer = ByteBuffer.wrap(Base64.decode(
        encoded.getBytes(Charset.forName("US-ASCII"))));
LongBuffer longBuffer = uuidBuffer.asLongBuffer();
UUID uuid = new UUID(longBuffer.get(), longBuffer.get());

Upvotes: 5

Related Questions