package net.i2p.util;
// uncomment to test reference implementation
//import com.github.emboss.siphash.*;
import net.i2p.crypto.SipHashInline;
/**
* Wrapper around SipHashInline with constant per-JVM keys
*
* @since 0.9.5
*/
public abstract class SipHash {
private static final long K0 = RandomSource.getInstance().nextLong();
private static final long K1 = RandomSource.getInstance().nextLong();
/**
* @param data non-null
*/
public static long digest(byte[] data) {
return SipHashInline.hash24(K0, K1, data);
}
/**
* @param data non-null
*/
public static long digest(byte[] data, int off, int len) {
return SipHashInline.hash24(K0, K1, data, off, len);
}
/**
* Secure replacement for DataHelper.hashCode(byte[]);
* caching recommended
*
* @param data may be null
*/
public static int hashCode(byte[] data) {
if (data == null) return 0;
return (int) SipHashInline.hash24(K0, K1, data);
}
/****
public static void main(String args[]) {
final int warmup = 10000;
final int runs = 1000000;
final byte[] b = new byte[32];
RandomSource.getInstance().nextBytes(b);
// inline implementation
for (int i = 0; i < warmup; i++) {
digest(b);
}
long begin = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
digest(b);
}
System.out.println("Inline impl. time per hash (us): " + (1000d * (System.currentTimeMillis() - begin) / runs));
// reference implementation
final byte[] key = new byte[16];
RandomSource.getInstance().nextBytes(key);
final SipKey sk = new SipKey(key);
for (int i = 0; i < warmup; i++) {
com.github.emboss.siphash.SipHash.digest(sk, b);
}
begin = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
com.github.emboss.siphash.SipHash.digest(sk, b);
}
System.out.println("Ref. impl. time per hash (us): " + (1000d * (System.currentTimeMillis() - begin) / runs));
// test results (eeepc openjdk 6) ~2.05 us inline, 2.75 us stock, inline ~25% faster
// test results (hexcore openjdk 7) ~0.07 us inline, 0.11 us stock, inline ~35% faster
}
****/
}