Advertisement
Guest User

Untitled

a guest
Jun 26th, 2017
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.46 KB | None | 0 0
  1. import sun.misc.Contended;
  2.  
  3. import java.security.NoSuchAlgorithmException;
  4. import java.security.SecureRandom;
  5. import java.util.Random;
  6. import java.util.concurrent.ForkJoinPool;
  7. import java.util.concurrent.RecursiveAction;
  8. import java.util.concurrent.ThreadLocalRandom;
  9. import java.util.concurrent.TimeUnit;
  10. import java.util.concurrent.atomic.LongAccumulator;
  11.  
  12. /**
  13. * Created by jcairns on 6/20/17.
  14. */
  15. public class Fnv1Collision {
  16.  
  17. // private static final String idfa = "6D92078A-8246-4BA4-AE5B-76104861E7DC";
  18.  
  19. private static final long FNV_64_INIT = 0xcbf29ce484222325L;
  20. private static final long FNV_64_PRIME = 0x100000001b3L;
  21.  
  22. private final String id;
  23. private final long hash;
  24.  
  25. private final ForkJoinPool forkPool = new ForkJoinPool();
  26.  
  27. private volatile boolean foundCollision;
  28.  
  29. private final Random secureRandom;
  30.  
  31. @Contended
  32. private LongAccumulator currentCount = new LongAccumulator((x, y) -> x+y, 0L);
  33.  
  34. public static void main(String[] arg) throws NoSuchAlgorithmException {
  35. final Fnv1Collision fnv1 = new Fnv1Collision();
  36. fnv1.checkCollisionRate();
  37. }
  38.  
  39. private Fnv1Collision() throws NoSuchAlgorithmException {
  40. foundCollision = false;
  41.  
  42. secureRandom = new SecureRandom();
  43.  
  44. id = generateIdfa(secureRandom);
  45.  
  46. hash = hash64(id);
  47. }
  48.  
  49. // expect a hash collision around 1 in 10B identifiers
  50. private void checkCollisionRate() {
  51. final long startTime = System.nanoTime();
  52.  
  53. final int nPar = forkPool.getParallelism();
  54.  
  55. final long hashSpace = 1_000_000_000_000L;
  56.  
  57. final long rangeSize = hashSpace/nPar;
  58. for(long h=0L; h<hashSpace; h+= rangeSize) {
  59. final RecursiveAction action = new CheckCollisionsRecursiveAction(h, h+rangeSize);
  60. forkPool.execute(action);
  61. }
  62.  
  63. while(forkPool.getActiveThreadCount() == 0) {
  64. Thread.yield();
  65. }
  66.  
  67. long lastCount = 0;
  68. while(!foundCollision && forkPool.getActiveThreadCount() > 0) {
  69. if(lastCount < currentCount.get()) {
  70. lastCount = currentCount.get();
  71. final long runTime = System.nanoTime() - startTime;
  72. System.out.println(lastCount/1_000_000 + ", " + String.format("%10.2f", lastCount*1e9/runTime)+"/s");
  73. }
  74.  
  75. try {
  76. Thread.sleep(250L);
  77. } catch (InterruptedException e) {
  78. e.printStackTrace();
  79. }
  80.  
  81. }
  82.  
  83. if(!foundCollision) {
  84. System.out.println("Key space exhausted. Try again.");
  85. }
  86.  
  87. final long time = TimeUnit.SECONDS.convert(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
  88. System.out.println("Elapsed time: " + time + " s");
  89.  
  90. }
  91.  
  92. private String generateIdfa(final Random random) {
  93. final String l1 = Long.toHexString(getLong8Hex(random));
  94. final String l2 = Long.toHexString(getLong8Hex(random));
  95. final String l3 = Long.toHexString(getLong8Hex(random));
  96. final String l4 = Long.toHexString(getLong8Hex(random));
  97. return new StringBuilder(40).append(l1).append('-').append(l2.substring(0, 4)).append('-').append(l2.substring(4, 8)).append('-').append(l3.substring(0, 4)).append('-').append(l3.substring(4, 8)).append(l4.substring(0, 8)).toString().toUpperCase();
  98. }
  99.  
  100. private long getLong8Hex(final Random random) {
  101. final long minVal = 0x10000000L;
  102. long h = random.nextLong() & 0xffffffffffffffffL;
  103. while(h < minVal) {
  104. h = random.nextLong() & 0xffffffffffffffffL;
  105. }
  106. return h;
  107. }
  108.  
  109. private long hash64(final String s) {
  110. long rv = FNV_64_INIT;
  111. final int n = s.length();
  112. for (int i = 0; i < n; i++) {
  113. rv *= FNV_64_PRIME;
  114. rv ^= s.charAt(i);
  115. }
  116. return rv;
  117. }
  118.  
  119. private final class CheckCollisionsRecursiveAction extends RecursiveAction {
  120.  
  121. public static final long CHUNK_COUNT = 1L<<20;
  122. public static final long RAND_COUNT = 1L<<10;
  123.  
  124. final long xMin;
  125. final long xMax;
  126.  
  127. private CheckCollisionsRecursiveAction(long xMin, long xMax) {
  128. this.xMin = xMin;
  129. this.xMax = xMax;
  130. }
  131.  
  132.  
  133. @Override
  134. protected void compute() {
  135.  
  136. try {
  137. final Random random = new Random(secureRandom.nextLong());
  138.  
  139. for (long i = xMin; !foundCollision && i < xMax; i++) {
  140. final String a1 = generateIdfa(random);
  141. final long l = hash64(a1);
  142.  
  143. if (hash == l) {
  144. if (!id.equals(a1)) {
  145. System.out.println("Collision found after " + i + " iterations.");
  146. System.out.println(a1 + " collides with " + id + " at value " + l + "=" + hash);
  147. foundCollision = true;
  148. break;
  149. }
  150. }
  151.  
  152. final long count = i - xMin;
  153. if (count > 0 && ((count & CHUNK_COUNT - 1) == 0)) {
  154. currentCount.accumulate(CHUNK_COUNT);
  155. }
  156.  
  157. if (count > 0 && ((count & RAND_COUNT - 1) == 0)) {
  158. random.setSeed(secureRandom.nextLong());
  159. }
  160. }
  161. } catch(final Throwable t) {
  162. System.out.println("Compute failed, unexpected exception.");
  163. t.printStackTrace(System.out);
  164. }
  165. }
  166. }
  167. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement