Skip to content

Instantly share code, notes, and snippets.

@lordmulder
Last active February 5, 2019 21:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lordmulder/b0206ca837a57738c90a0194623bb993 to your computer and use it in GitHub Desktop.
Save lordmulder/b0206ca837a57738c90a0194623bb993 to your computer and use it in GitHub Desktop.
Collect some additional entropy from timers (for seeding purpose)
/*
* Seeder
* Created by LoRd_MuldeR <mulder2@gmx.de>.
*
* This work is licensed under the CC0 1.0 Universal License.
* To view a copy of the license, visit:
* https://creativecommons.org/publicdomain/zero/1.0/legalcode
*/
package com.mulderosft.crypto.seeder;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.codec.binary.Hex;
import it.unimi.dsi.fastutil.Hash.Strategy;
import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet;
public class Seeder {
private static final int COLLECT_ROUNDS = 31;
/**
* Collect some additional entropy from timers, for seeding only
*/
static byte[] collectEntropy(final int length) {
final byte[] output = new byte[length];
final Set<Integer> s1 = new HashSet<Integer>((length + Long.BYTES - 1) / Long.BYTES);
final Set<Integer> s2 = new HashSet<Integer>(COLLECT_ROUNDS);
int pos = 0;
while (pos < length) {
long value;
do {
value = 0xCBF29CE484222325L;
s2.clear();
for (int i = 0; i < COLLECT_ROUNDS; i++) {
long r1, r2, q;
do {
r1 = (31L * System.currentTimeMillis()) + System.nanoTime();
r2 = (31L * System.currentTimeMillis()) + System.nanoTime();
} while (!s2.add(Long.hashCode(q = r2 ^ r1)));
for(int j = 0; j < Integer.BYTES; ++j) {
value = 1099511628211L * (value ^ ((q >>> (j * Byte.SIZE)) & 0xFFL));
}
}
} while (!s1.add(Long.hashCode(value)));
final int remain = Math.min(Long.BYTES, length - pos);
for(int i = 0; i < remain; ++i) {
output[pos++] = (byte) ((value >>> (i * Byte.SIZE)) & 0xFFL);
}
}
return output;
}
//=======================================================================
// TEST
//=======================================================================
private static class ByteArrayStrategy implements Strategy<byte[]> {
@Override
public boolean equals(byte[] a, byte[] b) {
return Arrays.equals(a, b);
}
@Override
public int hashCode(byte[] a) {
return Arrays.hashCode(a);
}
}
public static void main(String[] args) {
System.err.printf("Seeding v18 [r=%d]\n", COLLECT_ROUNDS);
boolean quiet = false;
for(final String argv : args ) {
if(argv.equalsIgnoreCase("--quiet")) {
quiet = true;
}
}
try {
runTest(quiet);
}
catch(Throwable e) {
System.err.println("[ERROR] " + e.getClass().getSimpleName() + ": " + e.getMessage());
}
System.err.println("Test completed.");
}
private static void runTest(final boolean quiet) {
final ObjectOpenCustomHashSet<byte[]> db = new ObjectOpenCustomHashSet<byte[]>(new ByteArrayStrategy());
try {
for (;;) {
final byte[] seed = collectEntropy(64);
if(!quiet) {
System.out.println(Hex.encodeHexString(seed));
}
if (!db.add(seed)) {
System.err.println("DUPLICATE FOUND !!!");
break;
}
if (db.size() % 10000 == 0) {
System.err.printf("Size: %,d\n", db.size());
}
}
}
finally {
System.err.printf("Size: %,d\n", db.size());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment