Bitwise

Context

I have a legacy identifier with a reference implementation is JS. I need to generate IDs in Java.

I rarely have to think about bitwise operations, so this problem started out frustrating, but I developed an appreciation for the elegance of binary, hex and bitwise operations as I warmed up, and was reluctant to trade them in for the relatively self-documenting Java syntax at the end.

JS

We use an array of 8-bit, unsigned ints:

var ints = new Uint8Array(8)

Presumably, this is because unsigned ints are byte-like (0-255).

We populate this array with random values:

window.crypto.getRandomValues(ints)

We get the last (random) 4 bits of the first byte using the AND operator against 1111 (0xF in hex):

var rand = 0xF & ints[0]

We prepend 0111 by adding 011100000 (0x70 in hex):

ints[0] = 0x70 + rand

I think this may be due to max long in Java, ie Long.MAX_VALUE == 0x7FFF_FFFF_FFFF_FFFFL.

We convert this to an array of chars and then base64 encode:

btoa(String.fromCharCode(...ints))

I think the base64 encoding is to retain the integrity of the “bytes”.

Sanity:

> atob("ekMJT1sVNBc=").split('').map(c=>c.charCodeAt(0))
< [122, 67, 9, 79, 91, 21, 52, 23]

Java

Java makes this easier with native 64 bit long, byte primitives and convenience classes. Java REPL makes it easy to hack around.

Decode

import java.nio.ByteBuffer
import java.util.Base64
String encoded = "ekMJT1sVNBc="
byte[] bytes = Base64.getDecoder().decode(encoded)
long id = ByteBuffer.wrap(bytes).getLong()

Encode

Generate a random long within a range 0x7…:

import java.util.Random
long id = new Random().longs(0x7000_0000_0000_0000L, Long.MAX_VALUE).limit(1).findFirst().getAsLong()

Convert to bytes:

byte[] bytes = ByteBuffer.allocate(Long.BYTES).putLong(id).array()

Encode:

Base64.getEncoder().encodeToString(bytes)

Sanity:

Long.toHexString(id)
Long.toBinaryString(id)

Feedback

Thoughts? Suggestions? Hit me up @erikeldridge

License

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 International License, and code samples are licensed under the MIT license.