提交 06dc8538 authored 作者: Thomas Mueller Graf's avatar Thomas Mueller Graf

Supplemental hash function for 64-bit numbers

上级 61873c88
...@@ -34,7 +34,7 @@ public class CalculateHashConstantLong implements Runnable { ...@@ -34,7 +34,7 @@ public class CalculateHashConstantLong implements Runnable {
private final AES aes = new AES(); private final AES aes = new AES();
{ {
aes.setKey("Hello Welt Hallo Welt".getBytes()); aes.setKey("Hello World Hallo Welt".getBytes());
} }
private final byte[] data = new byte[16]; private final byte[] data = new byte[16];
...@@ -54,6 +54,39 @@ public class CalculateHashConstantLong implements Runnable { ...@@ -54,6 +54,39 @@ public class CalculateHashConstantLong implements Runnable {
for (int i = 0; i < randomValues.length; i++) { for (int i = 0; i < randomValues.length; i++) {
randomValues[i] = r.nextInt(); randomValues[i] = r.nextInt();
} }
printQuality(new CalculateHashConstantLong() {
@Override
public long hash(long x) {
return secureHash(x);
}
@Override
public String toString() {
return "AES";
}
}, randomValues);
// Quality of AES
// Dependencies: 15715..16364
// Avalanche: 31998
// AvalancheSum: 3199841
// Effect: 49456..50584
printQuality(new CalculateHashConstantLong() {
@Override
public long hash(long x) {
x = (x ^ (x >>> 30)) * 0xbf58476d1ce4e5b9L;
x = (x ^ (x >>> 27)) * 0x94d049bb133111ebL;
return x ^ (x >>> 31);
}
@Override
public String toString() {
return "Test";
}
}, randomValues);
// Quality of Test
// Dependencies: 14693..16502
// Avalanche: 31996
// AvalancheSum: 3199679
// Effect: 49437..50537
Thread[] threads = new Thread[8]; Thread[] threads = new Thread[8];
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
...@@ -67,28 +100,8 @@ public class CalculateHashConstantLong implements Runnable { ...@@ -67,28 +100,8 @@ public class CalculateHashConstantLong implements Runnable {
int finalCount = 10000; int finalCount = 10000;
long[] randomValues = getRandomValues(finalCount, 10); long[] randomValues = getRandomValues(finalCount, 10);
System.out.println(); CalculateHashConstantLong test;
System.out.println("AES:");
CalculateHashConstantLong test = new CalculateHashConstantLong();
int[] minMax; int[] minMax;
int av = 0;
test = new CalculateHashConstantLong() {
@Override
public long hash(long x) {
return secureHash(x);
}
};
minMax = test.getDependencies(test, randomValues);
System.out.println("Dependencies: " + minMax[0] + ".." + minMax[1]);
av = 0;
for (int j = 0; j < 100; j++) {
av += test.getAvalanche(test, randomValues[j]);
}
System.out.println("Avalanche: " + (av / 100));
System.out.println("AvalancheSum: " + av);
minMax = test.getEffect(test, finalCount * 10, 11);
System.out.println("Effect: " + minMax[0] + ".." + minMax[1]);
test = new CalculateHashConstantLong(); test = new CalculateHashConstantLong();
long best = 0; long best = 0;
int dist = Integer.MAX_VALUE; int dist = Integer.MAX_VALUE;
...@@ -99,7 +112,7 @@ public class CalculateHashConstantLong implements Runnable { ...@@ -99,7 +112,7 @@ public class CalculateHashConstantLong implements Runnable {
minMax = test.getDependencies(test, randomValues); minMax = test.getDependencies(test, randomValues);
System.out.println("Dependencies: " + minMax[0] + ".." + minMax[1]); System.out.println("Dependencies: " + minMax[0] + ".." + minMax[1]);
int d = minMax[1] - minMax[0]; int d = minMax[1] - minMax[0];
av = 0; int av = 0;
for (int j = 0; j < 100; j++) { for (int j = 0; j < 100; j++) {
av += test.getAvalanche(test, randomValues[j]); av += test.getAvalanche(test, randomValues[j]);
} }
...@@ -119,6 +132,24 @@ public class CalculateHashConstantLong implements Runnable { ...@@ -119,6 +132,24 @@ public class CalculateHashConstantLong implements Runnable {
System.out.println("Collisions: " + collisions); System.out.println("Collisions: " + collisions);
} }
static void printQuality(CalculateHashConstantLong test, long[] randomValues) {
int finalCount = randomValues.length * 10;
System.out.println("Quality of " + test);
int[] minMax;
int av = 0;
minMax = test.getDependencies(test, randomValues);
System.out.println("Dependencies: " + minMax[0] + ".." + minMax[1]);
av = 0;
for (int j = 0; j < 100; j++) {
av += test.getAvalanche(test, randomValues[j]);
}
System.out.println("Avalanche: " + (av / 100));
System.out.println("AvalancheSum: " + av);
minMax = test.getEffect(test, finalCount * 10, 11);
System.out.println("Effect: " + minMax[0] + ".." + minMax[1]);
System.out.println("ok=" + test.testCandidate());
}
/** /**
* Store a random file to be analyzed by the Diehard test. * Store a random file to be analyzed by the Diehard test.
*/ */
...@@ -169,42 +200,44 @@ public class CalculateHashConstantLong implements Runnable { ...@@ -169,42 +200,44 @@ public class CalculateHashConstantLong implements Runnable {
} }
long i = (currentHigh << 48) | ((long) low << 32) | (currentHigh << 16) | low; long i = (currentHigh << 48) | ((long) low << 32) | (currentHigh << 16) | low;
constant = i; constant = i;
// after one bit changes in the input, if (!testCandidate()) {
// on average 32 bits of the output change
int av = getAvalanche(this, 0);
if (Math.abs(av - 28057) > 1000) {
continue;
}
av = getAvalanche(this, 0xffffffffffffffffL);
if (Math.abs(av - 28057) > 1000) {
continue;
}
long es = getEffectSquare(this, randomValues);
if (es > 54379333) {
continue;
}
int[] minMax = getEffect(this, 10000, 1);
if (!isWithin(1500, 10000, minMax)) {
continue;
}
minMax = getDependencies(this, randomValues);
System.out.println(i + " minMax " + minMax[0] + " " + minMax[1]);
// aes: 117693..162049
if (!isWithin(13063, 21744, minMax)) {
continue;
}
minMax = getEffect(this, 100000, 3);
System.out.println(i + " minMax2 " + minMax[0] + " " + minMax[1]);
if (!isWithin(15143, 82527, minMax)) {
continue; continue;
} }
System.out.println(Long.toHexString(i) + System.out.println(Long.toHexString(i) +
" hit av:" + av + " bits:" + Long.bitCount(i) + " es:" + es + " prime:" + " hit " + i);
BigInteger.valueOf(i).isProbablePrime(15));
candidates.add(i); candidates.add(i);
} }
} }
private boolean testCandidate() {
// after one bit changes in the input,
// on average 32 bits of the output change
int av = getAvalanche(this, 0);
if (Math.abs(av - 32000) > 1000) {
return false;
}
av = getAvalanche(this, 0xffffffffffffffffL);
if (Math.abs(av - 32000) > 1000) {
return false;
}
long es = getEffectSquare(this, randomValues);
if (es > 1100000) {
System.out.println("fail at a " + es);
return false;
}
int[] minMax = getEffect(this, 10000, 1);
if (!isWithin(4700, 5300, minMax)) {
System.out.println("fail at b " + minMax[0] + " " + minMax[1]);
return false;
}
minMax = getDependencies(this, randomValues);
if (!isWithin(14500, 17000, minMax)) {
System.out.println("fail at c " + minMax[0] + " " + minMax[1]);
return false;
}
return true;
}
long getCollisionCount() { long getCollisionCount() {
// TODO need a way to check this // TODO need a way to check this
return 0; return 0;
...@@ -316,7 +349,7 @@ System.out.println(i + " minMax2 " + minMax[0] + " " + minMax[1]); ...@@ -316,7 +349,7 @@ System.out.println(i + " minMax2 " + minMax[0] + " " + minMax[1]);
} }
/** /**
* Calculate if the all bit changes (that an output bit changes if an input * Calculate if the bit changes (that an output bit changes if an input
* bit is changed) are within a certain range. * bit is changed) are within a certain range.
* *
* @param h the hash object * @param h the hash object
...@@ -360,7 +393,6 @@ System.out.println(i + " minMax2 " + minMax[0] + " " + minMax[1]); ...@@ -360,7 +393,6 @@ System.out.println(i + " minMax2 " + minMax[0] + " " + minMax[1]);
* @return the output * @return the output
*/ */
long hash(long x) { long hash(long x) {
// return secureHash(x);
x = ((x >>> 32) ^ x) * constant; x = ((x >>> 32) ^ x) * constant;
x = ((x >>> 32) ^ x) * constant; x = ((x >>> 32) ^ x) * constant;
x = (x >>> 32) ^ x; x = (x >>> 32) ^ x;
...@@ -374,7 +406,6 @@ System.out.println(i + " minMax2 " + minMax[0] + " " + minMax[1]); ...@@ -374,7 +406,6 @@ System.out.println(i + " minMax2 " + minMax[0] + " " + minMax[1]);
* @return the output * @return the output
*/ */
long secureHash(long x) { long secureHash(long x) {
Arrays.fill(data, (byte) 0);
writeLong(data, 0, x); writeLong(data, 0, x);
aes.encrypt(data, 0, 16); aes.encrypt(data, 0, 16);
return readLong(data, 0); return readLong(data, 0);
...@@ -393,7 +424,7 @@ System.out.println(i + " minMax2 " + minMax[0] + " " + minMax[1]); ...@@ -393,7 +424,7 @@ System.out.println(i + " minMax2 " + minMax[0] + " " + minMax[1]);
} }
private static long readLong(byte[] buff, int pos) { private static long readLong(byte[] buff, int pos) {
return (((long) readInt(buff, pos)) << 32) | readInt(buff, pos + 4); return (((long) readInt(buff, pos)) << 32) | (readInt(buff, pos + 4) & 0xffffffffL);
} }
private static int readInt(byte[] buff, int pos) { private static int readInt(byte[] buff, int pos) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论