Last active
February 5, 2019 21:19
-
-
Save lordmulder/b0206ca837a57738c90a0194623bb993 to your computer and use it in GitHub Desktop.
Collect some additional entropy from timers (for seeding purpose)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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