forked from I2P_Developers/i2p.i2p
- 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:
@@ -72,6 +72,9 @@ Public domain except as listed below:
|
|||||||
Copyright (c) 2006, Matthew Estes
|
Copyright (c) 2006, Matthew Estes
|
||||||
See licenses/LICENSE-BlockFile.txt
|
See licenses/LICENSE-BlockFile.txt
|
||||||
|
|
||||||
|
SipHashInline:
|
||||||
|
Copyright 2012 Hiroshi Nakamura <nahi@ruby-lang.org>
|
||||||
|
See licenses/LICENSE-Apache2.0.txt
|
||||||
|
|
||||||
Router (router.jar):
|
Router (router.jar):
|
||||||
Public domain except as listed below:
|
Public domain except as listed below:
|
||||||
|
@@ -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.RandomSource;
|
||||||
import net.i2p.util.SimpleByteCache;
|
import net.i2p.util.SimpleByteCache;
|
||||||
|
import net.i2p.util.SipHash;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 32 bytes, usually of random data.
|
* 32 bytes, usually of random data.
|
||||||
@@ -18,6 +22,7 @@ import net.i2p.util.SimpleByteCache;
|
|||||||
*/
|
*/
|
||||||
public class SessionTag extends SimpleDataStructure {
|
public class SessionTag extends SimpleDataStructure {
|
||||||
public final static int BYTE_LENGTH = 32;
|
public final static int BYTE_LENGTH = 32;
|
||||||
|
private int _cachedHashCode;
|
||||||
|
|
||||||
public SessionTag() {
|
public SessionTag() {
|
||||||
super();
|
super();
|
||||||
@@ -31,6 +36,7 @@ public class SessionTag extends SimpleDataStructure {
|
|||||||
if (create) {
|
if (create) {
|
||||||
_data = SimpleByteCache.acquire(BYTE_LENGTH);
|
_data = SimpleByteCache.acquire(BYTE_LENGTH);
|
||||||
RandomSource.getInstance().nextBytes(_data);
|
RandomSource.getInstance().nextBytes(_data);
|
||||||
|
_cachedHashCode = SipHash.hashCode(_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,4 +47,27 @@ public class SessionTag extends SimpleDataStructure {
|
|||||||
public int length() {
|
public int length() {
|
||||||
return BYTE_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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
75
core/java/src/net/i2p/util/SipHash.java
Normal file
75
core/java/src/net/i2p/util/SipHash.java
Normal 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
|
||||||
|
}
|
||||||
|
****/
|
||||||
|
}
|
@@ -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.
|
* SipHash implementation with hand inlining the SIPROUND.
|
||||||
*
|
*
|
||||||
@@ -7,17 +30,25 @@
|
|||||||
* SIPROUND is defined in siphash24.c that can be downloaded from the above
|
* 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
|
* site. Following license notice is subject to change based on the licensing
|
||||||
* policy of siphash24.c.
|
* 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) {
|
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 v0 = 0x736f6d6570736575L ^ k0;
|
||||||
long v1 = 0x646f72616e646f6dL ^ k1;
|
long v1 = 0x646f72616e646f6dL ^ k1;
|
||||||
long v2 = 0x6c7967656e657261L ^ k0;
|
long v2 = 0x6c7967656e657261L ^ k0;
|
||||||
long v3 = 0x7465646279746573L ^ k1;
|
long v3 = 0x7465646279746573L ^ k1;
|
||||||
long m;
|
long m;
|
||||||
int last = data.length / 8 * 8;
|
int last = len / 8 * 8;
|
||||||
int i = 0;
|
int i = off;
|
||||||
|
|
||||||
// processing 8 bytes blocks in data
|
// processing 8 bytes blocks in data
|
||||||
while (i < last) {
|
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
|
// packing the last block to long, as LE 0-7 bytes + the length in the top byte
|
||||||
m = 0;
|
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 <<= 8; m |= (long) data[i];
|
||||||
}
|
}
|
||||||
m |= (long) data.length << 56;
|
m |= (long) len << 56;
|
||||||
// MSGROUND {
|
// MSGROUND {
|
||||||
v3 ^= m;
|
v3 ^= m;
|
||||||
// SIPROUND {
|
// SIPROUND {
|
||||||
|
@@ -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;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
public class SipHashInlineTest extends TestCase {
|
public class SipHashInlineTest extends TestCase {
|
||||||
|
@@ -19,6 +19,7 @@ public class UtilTestSuite {
|
|||||||
suite.addTestSuite(ResettableGZIPOutputStreamTest.class);
|
suite.addTestSuite(ResettableGZIPOutputStreamTest.class);
|
||||||
suite.addTestSuite(ReusableGZIPInputStreamTest.class);
|
suite.addTestSuite(ReusableGZIPInputStreamTest.class);
|
||||||
suite.addTestSuite(ReusableGZIPOutputStreamTest.class);
|
suite.addTestSuite(ReusableGZIPOutputStreamTest.class);
|
||||||
|
suite.addTestSuite(SipHashInlineTest.class);
|
||||||
|
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
13
history.txt
13
history.txt
@@ -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
|
2013-01-01 kytv
|
||||||
* Update Java Service Wrapper to v3.5.17 (ticket #826).
|
* Update Java Service Wrapper to v3.5.17 (ticket #826).
|
||||||
- Windows: Self-compiled with VS2010 in Windows 7. The icon has been
|
- Windows: Self-compiled with VS2010 in Windows 7. The icon has been
|
||||||
|
@@ -18,7 +18,7 @@ public class RouterVersion {
|
|||||||
/** deprecated */
|
/** deprecated */
|
||||||
public final static String ID = "Monotone";
|
public final static String ID = "Monotone";
|
||||||
public final static String VERSION = CoreVersion.VERSION;
|
public final static String VERSION = CoreVersion.VERSION;
|
||||||
public final static long BUILD = 3;
|
public final static long BUILD = 4;
|
||||||
|
|
||||||
/** for example "-test" */
|
/** for example "-test" */
|
||||||
public final static String EXTRA = "";
|
public final static String EXTRA = "";
|
||||||
|
Reference in New Issue
Block a user