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
|
||||
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:
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
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.
|
||||
*
|
||||
@@ -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 {
|
||||
|
@@ -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 {
|
||||
|
@@ -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;
|
||||
}
|
||||
|
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
|
||||
* Update Java Service Wrapper to v3.5.17 (ticket #826).
|
||||
- Windows: Self-compiled with VS2010 in Windows 7. The icon has been
|
||||
|
@@ -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 = "";
|
||||
|
Reference in New Issue
Block a user