Search code examples
javaencodinguuid

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.


Solution

  • 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());