- Local mods and wrapper for SipHashInline

- Convert SessionTag.hashCode() to SipHash to prevent collision attacks
     in the SessionKeyManager; cache for speed
This commit is contained in:
zzz
2013-01-02 14:01:29 +00:00
parent 20cc48cd87
commit 6ed602309f
8 changed files with 182 additions and 7 deletions

View File

@@ -72,6 +72,9 @@ Public domain except as listed below:
Copyright (c) 2006, Matthew Estes
See licenses/LICENSE-BlockFile.txt
SipHashInline:
Copyright 2012 Hiroshi Nakamura <nahi@ruby-lang.org>
See licenses/LICENSE-Apache2.0.txt
Router (router.jar):
Public domain except as listed below:

View File

@@ -9,8 +9,12 @@ package net.i2p.data;
*
*/
import java.io.InputStream;
import java.io.IOException;
import net.i2p.util.RandomSource;
import net.i2p.util.SimpleByteCache;
import net.i2p.util.SipHash;
/**
* 32 bytes, usually of random data.
@@ -18,6 +22,7 @@ import net.i2p.util.SimpleByteCache;
*/
public class SessionTag extends SimpleDataStructure {
public final static int BYTE_LENGTH = 32;
private int _cachedHashCode;
public SessionTag() {
super();
@@ -31,6 +36,7 @@ public class SessionTag extends SimpleDataStructure {
if (create) {
_data = SimpleByteCache.acquire(BYTE_LENGTH);
RandomSource.getInstance().nextBytes(_data);
_cachedHashCode = SipHash.hashCode(_data);
}
}
@@ -41,4 +47,27 @@ public class SessionTag extends SimpleDataStructure {
public int length() {
return BYTE_LENGTH;
}
@Override
public void setData(byte[] data) {
super.setData(data);
_cachedHashCode = SipHash.hashCode(data);
}
@Override
public void readBytes(InputStream in) throws DataFormatException, IOException {
super.readBytes(in);
_cachedHashCode = SipHash.hashCode(_data);
}
/**
* SessionTags are generated both locally and by peers, in quantity,
* and are used as keys in several datastructures (see TransientSessionKeyManager),
* so we use a secure hashCode function.
*/
@Override
public int hashCode() {
return _cachedHashCode;
}
}

View File

@@ -0,0 +1,75 @@
package net.i2p.util;
// uncomment to test reference implementation
//import com.github.emboss.siphash.*;
/**
* Wrapper around SipHashInline
*
* @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
}
****/
}

View File

@@ -1,3 +1,26 @@
package net.i2p.util;
/*
* As pulled from https://github.com/nahi/siphash-java-inline
* Last commit was https://github.com/nahi/siphash-java-inline/commit/5be5c84851a28f800fcac66ced658bdbd01f31ef
* 2012-11-06
*
* Copyright 2012 Hiroshi Nakamura <nahi@ruby-lang.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/**
* SipHash implementation with hand inlining the SIPROUND.
*
@@ -7,17 +30,25 @@
* SIPROUND is defined in siphash24.c that can be downloaded from the above
* site. Following license notice is subject to change based on the licensing
* policy of siphash24.c.
*
* I2P mods: add off/len version
*
* @since 0.9.5
*/
public class SipHashInline {
abstract class SipHashInline {
public static long hash24(long k0, long k1, byte[] data) {
return hash24(k0, k1, data, 0, data.length);
}
public static long hash24(long k0, long k1, byte[] data, int off, int len) {
long v0 = 0x736f6d6570736575L ^ k0;
long v1 = 0x646f72616e646f6dL ^ k1;
long v2 = 0x6c7967656e657261L ^ k0;
long v3 = 0x7465646279746573L ^ k1;
long m;
int last = data.length / 8 * 8;
int i = 0;
int last = len / 8 * 8;
int i = off;
// processing 8 bytes blocks in data
while (i < last) {
@@ -100,10 +131,10 @@ public class SipHashInline {
// packing the last block to long, as LE 0-7 bytes + the length in the top byte
m = 0;
for (i = data.length - 1; i >= last; --i) {
for (i = off + len - 1; i >= last; --i) {
m <<= 8; m |= (long) data[i];
}
m |= (long) data.length << 56;
m |= (long) len << 56;
// MSGROUND {
v3 ^= m;
// SIPROUND {

View File

@@ -1,3 +1,26 @@
package net.i2p.util;
/*
* As pulled from https://github.com/nahi/siphash-java-inline
* Last commit was https://github.com/nahi/siphash-java-inline/commit/5be5c84851a28f800fcac66ced658bdbd01f31ef
* 2012-11-06
*
* Copyright 2012 Hiroshi Nakamura <nahi@ruby-lang.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import junit.framework.TestCase;
public class SipHashInlineTest extends TestCase {

View File

@@ -19,6 +19,7 @@ public class UtilTestSuite {
suite.addTestSuite(ResettableGZIPOutputStreamTest.class);
suite.addTestSuite(ReusableGZIPInputStreamTest.class);
suite.addTestSuite(ReusableGZIPOutputStreamTest.class);
suite.addTestSuite(SipHashInlineTest.class);
return suite;
}

View File

@@ -1,3 +1,16 @@
2013-01-02 zzz
* DataHelper: new getASCII() method
* DataStructures:
- Convert SessionTag.hashCode() to SipHash to prevent collision attacks
- Improve equals()
* I2CP:
- Remove unused equals() methods for message classes
- Remove static logs
- Fix leak if nonce = 0 but reliability != none
- More work on failure codes (ticket #788)
* SAM: Synchronize dissector
* Transport: Fix early NPE (ticket #824)
2013-01-01 kytv
* Update Java Service Wrapper to v3.5.17 (ticket #826).
- Windows: Self-compiled with VS2010 in Windows 7. The icon has been

View File

@@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 3;
public final static long BUILD = 4;
/** for example "-test" */
public final static String EXTRA = "";