It's been a few days since we've done the Code Snippet Of the Day, so in lieu of Alex's normal article, here's your mid-day CodeSOD edited by Michael Casadevall ...

J.S. Bangs sends us today's snippit located deep within a Java codebase he's maintaining. The function, getRandomBits() returns a 32-byte array of random bites for security purposes. Since Java provides a Random method, this should be easy; in fact a proper implementation can be writting in five lines:

public static byte[] getRandomBits() {
byte[] random = new byte[32];
Random.nextBytes(random);
return random;
}

Of course, J.S.'s predecessor found a more interesting way to do things. His version of getRandomBits did its job by:

* Enumerate all of the System properties
* Create an MD4 hash of all of the property key/value pairs
* Do a bitwise-XOR of the various hashes
* Throw in an MD4 hash of the current system time so that the value isn't always the same
* Bitwise-XOR that in there as well
* Return the result

The best thing J.S. could say about this code was "at least it's commented". I don't believe it within my ability however to do this code justice, so without futher to do:

public static byte[] innerGetRandomBits() {
int pos = 0;
int iters = 0;

bits = new byte[(nbits + 7) / 8];

for (int i = 0; i < bits.length; i++)
bits[i] = (byte) 0;

Enumeration e = null;
try {
e = System.getProperties().propertyNames();
} catch (Exception ex) {
// no need to do anything
}

MD4 hash = new MD4();
int hash_count = 0;
int hash_bytes = 0;

long ms = System.currentTimeMillis();
byte[] bytes = new byte[12];
for (int i = 0; i < 8; i++) {
bytes[i] = (byte) (ms & 0xffL);
ms = ms >> 8;
}
int hn = System.identityHashCode(bytes);
for (int i = 0; i < 4; i++) {
bytes[i + 8] = (byte) (hn & 0xffL);
hn = hn >> 8;
}

if (e != null)
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
if (key != null) {
String val = System.getProperty(key);
if (val != null) {

String pair = key + val;
bytes = pair.getBytes();
hash.engineUpdate(bytes, 0, bytes.length);
hash_bytes += bytes.length;

// when the hash input size is large enough ...
if (hash_bytes >= 128) {
hash_count++;
hash_bytes = 0;

// ... produce a digest and ...
byte[] digest = hash.engineDigest();
for (int i = 0; i < digest.length; i++) {

// ...fold it into the bit buffer
bits[pos] = (byte) (bits[pos] ^ digest[i]);
pos++;
if (pos == bits.length) {
pos = 0;
iters++;
}
} // end for
} // end if hash_bytes
} // end if val non null
} // end if key non null
} // end while e.hasMoreElements

while (iters < 2) {
for (int j = 512 / 8; j > 0; j--) {
Thread.yield();
ms = System.currentTimeMillis();
for (int i = 0; i < 8; i++) {
bytes[i] = (byte) (ms & 0xffL);
ms = ms >> 8;
}
hash.engineUpdate(bytes, 0, 8);
hash_bytes += 8;

// when the hash input size is large enough ...
if (hash_bytes >= 128) {
hash_count++;
hash_bytes = 0;

// ... produce a digest and ...
byte[] digest = hash.engineDigest();
for (int i = 0; i < digest.length; i++) {

// ...fold it into the bit buffer
bits[pos] = (byte) (bits[pos] ^ digest[i]);
pos++;
if (pos == bits.length) {
pos = 0;
iters++;
}
} // end for
} // end if hash_bytes
} // end for
} // end while iters

return bits;
}