2005-07-05
* Use a buffered PRNG, pulling the PRNG data off a larger precalculated buffer, rather than the underlying PRNG's (likely small) one, which in turn reduces the frequency of recalcing. * More tuning to reduce temporary allocation churn
This commit is contained in:
@ -9,12 +9,16 @@ import net.i2p.data.Hash;
|
||||
import net.i2p.data.SessionKey;
|
||||
|
||||
import org.bouncycastle.crypto.digests.SHA256Digest;
|
||||
import org.bouncycastle.crypto.digests.MD5Digest;
|
||||
import org.bouncycastle.crypto.macs.HMac;
|
||||
|
||||
/**
|
||||
* Calculate the HMAC-SHA256 of a key+message. All the good stuff occurs
|
||||
* in {@link org.bouncycastle.crypto.macs.HMac} and
|
||||
* {@link org.bouncycastle.crypto.digests.SHA256Digest}.
|
||||
* {@link org.bouncycastle.crypto.digests.SHA256Digest}. Alternately, if
|
||||
* the context property "i2p.HMACMD5" is set to true, then this whole HMAC
|
||||
* generator will be transformed into HMACMD5, maintaining the same size and
|
||||
* using {@link org.bouncycastle.crypto.digests.MD5Digest}.
|
||||
*
|
||||
*/
|
||||
public class HMACSHA256Generator {
|
||||
@ -23,11 +27,18 @@ public class HMACSHA256Generator {
|
||||
private List _available;
|
||||
/** set of available byte[] buffers for verify */
|
||||
private List _availableTmp;
|
||||
private boolean _useMD5;
|
||||
|
||||
public static final boolean DEFAULT_USE_MD5 = true;
|
||||
|
||||
public HMACSHA256Generator(I2PAppContext context) {
|
||||
_context = context;
|
||||
_available = new ArrayList(32);
|
||||
_availableTmp = new ArrayList(32);
|
||||
if ("true".equals(context.getProperty("i2p.HMACMD5", Boolean.toString(DEFAULT_USE_MD5).toLowerCase())))
|
||||
_useMD5 = true;
|
||||
else
|
||||
_useMD5 = false;
|
||||
}
|
||||
|
||||
public static HMACSHA256Generator getInstance() {
|
||||
@ -40,12 +51,15 @@ public class HMACSHA256Generator {
|
||||
public Hash calculate(SessionKey key, byte data[]) {
|
||||
if ((key == null) || (key.getData() == null) || (data == null))
|
||||
throw new NullPointerException("Null arguments for HMAC");
|
||||
return calculate(key, data, 0, data.length);
|
||||
byte rv[] = new byte[Hash.HASH_LENGTH];
|
||||
calculate(key, data, 0, data.length, rv, 0);
|
||||
return new Hash(rv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the HMAC of the data with the given key
|
||||
*/
|
||||
/*
|
||||
public Hash calculate(SessionKey key, byte data[], int offset, int length) {
|
||||
if ((key == null) || (key.getData() == null) || (data == null))
|
||||
throw new NullPointerException("Null arguments for HMAC");
|
||||
@ -58,6 +72,23 @@ public class HMACSHA256Generator {
|
||||
release(mac);
|
||||
return new Hash(rv);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Calculate the HMAC of the data with the given key
|
||||
*/
|
||||
public void calculate(SessionKey key, byte data[], int offset, int length, byte target[], int targetOffset) {
|
||||
if ((key == null) || (key.getData() == null) || (data == null))
|
||||
throw new NullPointerException("Null arguments for HMAC");
|
||||
|
||||
HMac mac = acquire();
|
||||
mac.init(key.getData());
|
||||
mac.update(data, offset, length);
|
||||
//byte rv[] = new byte[Hash.HASH_LENGTH];
|
||||
mac.doFinal(target, targetOffset);
|
||||
release(mac);
|
||||
//return new Hash(rv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the MAC inline, reducing some unnecessary memory churn.
|
||||
@ -92,6 +123,9 @@ public class HMACSHA256Generator {
|
||||
if (_available.size() > 0)
|
||||
return (HMac)_available.remove(0);
|
||||
}
|
||||
if (_useMD5)
|
||||
return new HMac(new MD5Digest());
|
||||
else
|
||||
return new HMac(new SHA256Digest());
|
||||
}
|
||||
private void release(HMac mac) {
|
||||
|
@ -1,6 +1,8 @@
|
||||
package net.i2p.crypto;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.Hash;
|
||||
|
||||
@ -12,7 +14,10 @@ import org.bouncycastle.crypto.digests.SHA256Digest;
|
||||
*
|
||||
*/
|
||||
public final class SHA256Generator {
|
||||
public SHA256Generator(I2PAppContext context) {}
|
||||
private List _digests;
|
||||
public SHA256Generator(I2PAppContext context) {
|
||||
_digests = new ArrayList(32);
|
||||
}
|
||||
|
||||
public static final SHA256Generator getInstance() {
|
||||
return I2PAppContext.getGlobalContext().sha();
|
||||
@ -27,11 +32,35 @@ public final class SHA256Generator {
|
||||
}
|
||||
public final Hash calculateHash(byte[] source, int start, int len) {
|
||||
byte rv[] = new byte[Hash.HASH_LENGTH];
|
||||
SHA256Digest digest = new SHA256Digest();
|
||||
digest.update(source, start, len);
|
||||
digest.doFinal(rv, 0);
|
||||
calculateHash(source, start, len, rv, 0);
|
||||
return new Hash(rv);
|
||||
}
|
||||
public final void calculateHash(byte[] source, int start, int len, byte out[], int outOffset) {
|
||||
SHA256Digest digest = acquire();
|
||||
digest.update(source, start, len);
|
||||
digest.doFinal(out, outOffset);
|
||||
release(digest);
|
||||
}
|
||||
|
||||
private SHA256Digest acquire() {
|
||||
SHA256Digest rv = null;
|
||||
synchronized (_digests) {
|
||||
if (_digests.size() > 0)
|
||||
rv = (SHA256Digest)_digests.remove(0);
|
||||
}
|
||||
if (rv != null)
|
||||
rv.reset();
|
||||
else
|
||||
rv = new SHA256Digest();
|
||||
return rv;
|
||||
}
|
||||
private void release(SHA256Digest digest) {
|
||||
synchronized (_digests) {
|
||||
if (_digests.size() < 32) {
|
||||
_digests.add(digest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
||||
|
222
core/java/src/net/i2p/util/BufferedRandomSource.java
Normal file
222
core/java/src/net/i2p/util/BufferedRandomSource.java
Normal file
@ -0,0 +1,222 @@
|
||||
package net.i2p.util;
|
||||
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by jrandom in 2005 and released into the public domain
|
||||
* with no warranty of any kind, either expressed or implied.
|
||||
* It probably won't make your computer catch on fire, or eat
|
||||
* your children, but it might. Use at your own risk.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.crypto.EntropyHarvester;
|
||||
import net.i2p.data.Base64;
|
||||
import net.i2p.data.DataHelper;
|
||||
|
||||
/**
|
||||
* Allocate data out of a large buffer of data, rather than the PRNG's
|
||||
* (likely) small buffer to reduce the frequency of prng recalcs (though
|
||||
* the recalcs are now more time consuming).
|
||||
*
|
||||
*/
|
||||
public class BufferedRandomSource extends RandomSource {
|
||||
private byte _buffer[];
|
||||
private int _nextByte;
|
||||
private int _nextBit;
|
||||
private static volatile long _reseeds;
|
||||
|
||||
private static final int BUFFER_SIZE = 256*1024;
|
||||
|
||||
public BufferedRandomSource(I2PAppContext context) {
|
||||
super(context);
|
||||
context.statManager().createRateStat("prng.reseedCount", "How many times the prng has been reseeded", "Encryption", new long[] { 60*1000, 10*60*1000, 60*60*1000 } );
|
||||
_buffer = new byte[BUFFER_SIZE];
|
||||
refillBuffer();
|
||||
// stagger reseeding
|
||||
_nextByte = ((int)_reseeds-1) * 16 * 1024;
|
||||
}
|
||||
|
||||
private final void refillBuffer() {
|
||||
long before = System.currentTimeMillis();
|
||||
doRefillBuffer();
|
||||
long duration = System.currentTimeMillis() - before;
|
||||
if ( (_reseeds % 1) == 0)
|
||||
_context.statManager().addRateData("prng.reseedCount", _reseeds, duration);
|
||||
}
|
||||
|
||||
private synchronized final void doRefillBuffer() {
|
||||
super.nextBytes(_buffer);
|
||||
_nextByte = 0;
|
||||
_nextBit = 0;
|
||||
_reseeds++;
|
||||
}
|
||||
|
||||
private static final byte GOBBLE_MASK[] = { 0x0, // 0 bits
|
||||
0x1, // 1 bit
|
||||
0x3, // 2 bits
|
||||
0x7, // 3 bits
|
||||
0xF, // 4 bits
|
||||
0x1F, // 5 bits
|
||||
0x3F, // 6 bits
|
||||
0x7F, // 7 bits
|
||||
(byte)0xFF // 8 bits
|
||||
};
|
||||
|
||||
private synchronized final long nextBits(int numBits) {
|
||||
if (false) {
|
||||
long rv = 0;
|
||||
for (int curBit = 0; curBit < numBits; curBit++) {
|
||||
if (_nextBit >= 8) {
|
||||
_nextBit = 0;
|
||||
_nextByte++;
|
||||
}
|
||||
if (_nextByte >= BUFFER_SIZE)
|
||||
refillBuffer();
|
||||
rv += (_buffer[_nextByte] << curBit);
|
||||
_nextBit++;
|
||||
/*
|
||||
int avail = 8 - _nextBit;
|
||||
// this is not correct! (or is it?)
|
||||
rv += (_buffer[_nextByte] << 8 - avail);
|
||||
_nextBit += avail;
|
||||
numBits -= avail;
|
||||
if (_nextBit >= 8) {
|
||||
_nextBit = 0;
|
||||
_nextByte++;
|
||||
}
|
||||
*/
|
||||
}
|
||||
return rv;
|
||||
} else {
|
||||
long rv = 0;
|
||||
int curBit = 0;
|
||||
while (curBit < numBits) {
|
||||
if (_nextBit >= 8) {
|
||||
_nextBit = 0;
|
||||
_nextByte++;
|
||||
}
|
||||
if (_nextByte >= BUFFER_SIZE)
|
||||
refillBuffer();
|
||||
int gobbleBits = 8 - _nextBit;
|
||||
int want = numBits - curBit;
|
||||
if (gobbleBits > want)
|
||||
gobbleBits = want;
|
||||
curBit += gobbleBits;
|
||||
int shift = 8 - _nextBit - gobbleBits;
|
||||
int c = (_buffer[_nextByte] & (GOBBLE_MASK[gobbleBits] << shift));
|
||||
rv += ((c >>> shift) << (curBit-gobbleBits));
|
||||
_nextBit += gobbleBits;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized final void nextBytes(byte buf[]) {
|
||||
int outOffset = 0;
|
||||
while (outOffset < buf.length) {
|
||||
int availableBytes = BUFFER_SIZE - _nextByte - (_nextBit != 0 ? 1 : 0);
|
||||
if (availableBytes <= 0)
|
||||
refillBuffer();
|
||||
int start = BUFFER_SIZE - availableBytes;
|
||||
int writeSize = Math.min(buf.length - outOffset, availableBytes);
|
||||
System.arraycopy(_buffer, start, buf, outOffset, writeSize);
|
||||
outOffset += writeSize;
|
||||
_nextByte += writeSize;
|
||||
_nextBit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public final int nextInt(int n) {
|
||||
if (n <= 0) return 0;
|
||||
int val = ((int)nextBits(countBits(n))) % n;
|
||||
if (val < 0)
|
||||
return 0 - val;
|
||||
else
|
||||
return val;
|
||||
}
|
||||
|
||||
public final int nextInt() { return nextInt(Integer.MAX_VALUE); }
|
||||
|
||||
/**
|
||||
* Like the modified nextInt, nextLong(n) returns a random number from 0 through n,
|
||||
* including 0, excluding n.
|
||||
*/
|
||||
public final long nextLong(long n) {
|
||||
if (n <= 0) return 0;
|
||||
long val = nextBits(countBits(n)) % n;
|
||||
if (val < 0)
|
||||
return 0 - val;
|
||||
else
|
||||
return val;
|
||||
}
|
||||
|
||||
public final long nextLong() { return nextLong(Long.MAX_VALUE); }
|
||||
|
||||
static final int countBits(long val) {
|
||||
int rv = 0;
|
||||
while (val > Integer.MAX_VALUE) {
|
||||
rv += 31;
|
||||
val >>>= 31;
|
||||
}
|
||||
|
||||
while (val > 0) {
|
||||
rv++;
|
||||
val >>= 1;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* override as synchronized, for those JVMs that don't always pull via
|
||||
* nextBytes (cough ibm)
|
||||
*/
|
||||
public final boolean nextBoolean() {
|
||||
return nextBits(1) != 0;
|
||||
}
|
||||
|
||||
private static final double DOUBLE_DENOMENATOR = (double)(1L << 53);
|
||||
/** defined per javadoc ( ((nextBits(26)<<27) + nextBits(27)) / (1 << 53)) */
|
||||
public final double nextDouble() {
|
||||
long top = (((long)nextBits(26) << 27) + nextBits(27));
|
||||
return top / DOUBLE_DENOMENATOR;
|
||||
}
|
||||
private static final float FLOAT_DENOMENATOR = (float)(1 << 24);
|
||||
/** defined per javadoc (nextBits(24) / ((float)(1 << 24)) ) */
|
||||
public float nextFloat() {
|
||||
long top = nextBits(24);
|
||||
return top / FLOAT_DENOMENATOR;
|
||||
}
|
||||
public double nextGaussian() {
|
||||
// bah, unbuffered
|
||||
return super.nextGaussian();
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
||||
byte data[] = new byte[16*1024];
|
||||
for (int i = 0; i < data.length; i += 4) {
|
||||
long l = ctx.random().nextLong();
|
||||
if (l < 0) l = 0 - l;
|
||||
DataHelper.toLong(data, i, 4, l);
|
||||
}
|
||||
byte compressed[] = DataHelper.compress(data);
|
||||
System.out.println("Compressed: " + compressed.length);
|
||||
System.out.println("Orig: " + data.length + ": " + toString(data));
|
||||
}
|
||||
private static final String toString(byte data[]) {
|
||||
StringBuffer buf = new StringBuffer(data.length * 9);
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if ((data[i] & (1 << j)) != 0)
|
||||
buf.append('1');
|
||||
else
|
||||
buf.append('0');
|
||||
}
|
||||
buf.append(' ');
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
@ -27,7 +27,8 @@ public class PooledRandomSource extends RandomSource {
|
||||
_log = context.logManager().getLog(PooledRandomSource.class);
|
||||
_pool = new RandomSource[POOL_SIZE];
|
||||
for (int i = 0; i < POOL_SIZE; i++) {
|
||||
_pool[i] = new RandomSource(context);
|
||||
//_pool[i] = new RandomSource(context);
|
||||
_pool[i] = new BufferedRandomSource(context);
|
||||
_pool[i].nextBoolean();
|
||||
}
|
||||
_nextPool = 0;
|
||||
|
@ -22,9 +22,11 @@ import net.i2p.crypto.EntropyHarvester;
|
||||
public class RandomSource extends SecureRandom {
|
||||
private Log _log;
|
||||
private EntropyHarvester _entropyHarvester;
|
||||
protected I2PAppContext _context;
|
||||
|
||||
public RandomSource(I2PAppContext context) {
|
||||
super();
|
||||
_context = context;
|
||||
_log = context.logManager().getLog(RandomSource.class);
|
||||
// when we replace to have hooks for fortuna (etc), replace with
|
||||
// a factory (or just a factory method)
|
||||
|
302
core/java/src/org/bouncycastle/crypto/digests/MD5Digest.java
Normal file
302
core/java/src/org/bouncycastle/crypto/digests/MD5Digest.java
Normal file
@ -0,0 +1,302 @@
|
||||
package org.bouncycastle.crypto.digests;
|
||||
|
||||
|
||||
/**
|
||||
* implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
|
||||
*/
|
||||
public class MD5Digest
|
||||
extends GeneralDigest
|
||||
{
|
||||
private static final int DIGEST_LENGTH = 16;
|
||||
|
||||
private int H1, H2, H3, H4; // IV's
|
||||
|
||||
private int[] X = new int[16];
|
||||
private int xOff;
|
||||
|
||||
/**
|
||||
* Standard constructor
|
||||
*/
|
||||
public MD5Digest()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor. This will copy the state of the provided
|
||||
* message digest.
|
||||
*/
|
||||
public MD5Digest(MD5Digest t)
|
||||
{
|
||||
super(t);
|
||||
|
||||
H1 = t.H1;
|
||||
H2 = t.H2;
|
||||
H3 = t.H3;
|
||||
H4 = t.H4;
|
||||
|
||||
System.arraycopy(t.X, 0, X, 0, t.X.length);
|
||||
xOff = t.xOff;
|
||||
}
|
||||
|
||||
public String getAlgorithmName()
|
||||
{
|
||||
return "MD5";
|
||||
}
|
||||
|
||||
public int getDigestSize()
|
||||
{
|
||||
return DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
protected void processWord(
|
||||
byte[] in,
|
||||
int inOff)
|
||||
{
|
||||
X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
|
||||
| ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
|
||||
|
||||
if (xOff == 16)
|
||||
{
|
||||
processBlock();
|
||||
}
|
||||
}
|
||||
|
||||
protected void processLength(
|
||||
long bitLength)
|
||||
{
|
||||
if (xOff > 14)
|
||||
{
|
||||
processBlock();
|
||||
}
|
||||
|
||||
X[14] = (int)(bitLength & 0xffffffff);
|
||||
X[15] = (int)(bitLength >>> 32);
|
||||
}
|
||||
|
||||
private void unpackWord(
|
||||
int word,
|
||||
byte[] out,
|
||||
int outOff)
|
||||
{
|
||||
out[outOff] = (byte)word;
|
||||
out[outOff + 1] = (byte)(word >>> 8);
|
||||
out[outOff + 2] = (byte)(word >>> 16);
|
||||
out[outOff + 3] = (byte)(word >>> 24);
|
||||
}
|
||||
|
||||
public int doFinal(
|
||||
byte[] out,
|
||||
int outOff)
|
||||
{
|
||||
finish();
|
||||
|
||||
unpackWord(H1, out, outOff);
|
||||
unpackWord(H2, out, outOff + 4);
|
||||
unpackWord(H3, out, outOff + 8);
|
||||
unpackWord(H4, out, outOff + 12);
|
||||
|
||||
reset();
|
||||
|
||||
return DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* reset the chaining variables to the IV values.
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
super.reset();
|
||||
|
||||
H1 = 0x67452301;
|
||||
H2 = 0xefcdab89;
|
||||
H3 = 0x98badcfe;
|
||||
H4 = 0x10325476;
|
||||
|
||||
xOff = 0;
|
||||
|
||||
for (int i = 0; i != X.length; i++)
|
||||
{
|
||||
X[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// round 1 left rotates
|
||||
//
|
||||
private static final int S11 = 7;
|
||||
private static final int S12 = 12;
|
||||
private static final int S13 = 17;
|
||||
private static final int S14 = 22;
|
||||
|
||||
//
|
||||
// round 2 left rotates
|
||||
//
|
||||
private static final int S21 = 5;
|
||||
private static final int S22 = 9;
|
||||
private static final int S23 = 14;
|
||||
private static final int S24 = 20;
|
||||
|
||||
//
|
||||
// round 3 left rotates
|
||||
//
|
||||
private static final int S31 = 4;
|
||||
private static final int S32 = 11;
|
||||
private static final int S33 = 16;
|
||||
private static final int S34 = 23;
|
||||
|
||||
//
|
||||
// round 4 left rotates
|
||||
//
|
||||
private static final int S41 = 6;
|
||||
private static final int S42 = 10;
|
||||
private static final int S43 = 15;
|
||||
private static final int S44 = 21;
|
||||
|
||||
/*
|
||||
* rotate int x left n bits.
|
||||
*/
|
||||
private int rotateLeft(
|
||||
int x,
|
||||
int n)
|
||||
{
|
||||
return (x << n) | (x >>> (32 - n));
|
||||
}
|
||||
|
||||
/*
|
||||
* F, G, H and I are the basic MD5 functions.
|
||||
*/
|
||||
private int F(
|
||||
int u,
|
||||
int v,
|
||||
int w)
|
||||
{
|
||||
return (u & v) | (~u & w);
|
||||
}
|
||||
|
||||
private int G(
|
||||
int u,
|
||||
int v,
|
||||
int w)
|
||||
{
|
||||
return (u & w) | (v & ~w);
|
||||
}
|
||||
|
||||
private int H(
|
||||
int u,
|
||||
int v,
|
||||
int w)
|
||||
{
|
||||
return u ^ v ^ w;
|
||||
}
|
||||
|
||||
private int K(
|
||||
int u,
|
||||
int v,
|
||||
int w)
|
||||
{
|
||||
return v ^ (u | ~w);
|
||||
}
|
||||
|
||||
protected void processBlock()
|
||||
{
|
||||
int a = H1;
|
||||
int b = H2;
|
||||
int c = H3;
|
||||
int d = H4;
|
||||
|
||||
//
|
||||
// Round 1 - F cycle, 16 times.
|
||||
//
|
||||
a = rotateLeft((a + F(b, c, d) + X[ 0] + 0xd76aa478), S11) + b;
|
||||
d = rotateLeft((d + F(a, b, c) + X[ 1] + 0xe8c7b756), S12) + a;
|
||||
c = rotateLeft((c + F(d, a, b) + X[ 2] + 0x242070db), S13) + d;
|
||||
b = rotateLeft((b + F(c, d, a) + X[ 3] + 0xc1bdceee), S14) + c;
|
||||
a = rotateLeft((a + F(b, c, d) + X[ 4] + 0xf57c0faf), S11) + b;
|
||||
d = rotateLeft((d + F(a, b, c) + X[ 5] + 0x4787c62a), S12) + a;
|
||||
c = rotateLeft((c + F(d, a, b) + X[ 6] + 0xa8304613), S13) + d;
|
||||
b = rotateLeft((b + F(c, d, a) + X[ 7] + 0xfd469501), S14) + c;
|
||||
a = rotateLeft((a + F(b, c, d) + X[ 8] + 0x698098d8), S11) + b;
|
||||
d = rotateLeft((d + F(a, b, c) + X[ 9] + 0x8b44f7af), S12) + a;
|
||||
c = rotateLeft((c + F(d, a, b) + X[10] + 0xffff5bb1), S13) + d;
|
||||
b = rotateLeft((b + F(c, d, a) + X[11] + 0x895cd7be), S14) + c;
|
||||
a = rotateLeft((a + F(b, c, d) + X[12] + 0x6b901122), S11) + b;
|
||||
d = rotateLeft((d + F(a, b, c) + X[13] + 0xfd987193), S12) + a;
|
||||
c = rotateLeft((c + F(d, a, b) + X[14] + 0xa679438e), S13) + d;
|
||||
b = rotateLeft((b + F(c, d, a) + X[15] + 0x49b40821), S14) + c;
|
||||
|
||||
//
|
||||
// Round 2 - G cycle, 16 times.
|
||||
//
|
||||
a = rotateLeft((a + G(b, c, d) + X[ 1] + 0xf61e2562), S21) + b;
|
||||
d = rotateLeft((d + G(a, b, c) + X[ 6] + 0xc040b340), S22) + a;
|
||||
c = rotateLeft((c + G(d, a, b) + X[11] + 0x265e5a51), S23) + d;
|
||||
b = rotateLeft((b + G(c, d, a) + X[ 0] + 0xe9b6c7aa), S24) + c;
|
||||
a = rotateLeft((a + G(b, c, d) + X[ 5] + 0xd62f105d), S21) + b;
|
||||
d = rotateLeft((d + G(a, b, c) + X[10] + 0x02441453), S22) + a;
|
||||
c = rotateLeft((c + G(d, a, b) + X[15] + 0xd8a1e681), S23) + d;
|
||||
b = rotateLeft((b + G(c, d, a) + X[ 4] + 0xe7d3fbc8), S24) + c;
|
||||
a = rotateLeft((a + G(b, c, d) + X[ 9] + 0x21e1cde6), S21) + b;
|
||||
d = rotateLeft((d + G(a, b, c) + X[14] + 0xc33707d6), S22) + a;
|
||||
c = rotateLeft((c + G(d, a, b) + X[ 3] + 0xf4d50d87), S23) + d;
|
||||
b = rotateLeft((b + G(c, d, a) + X[ 8] + 0x455a14ed), S24) + c;
|
||||
a = rotateLeft((a + G(b, c, d) + X[13] + 0xa9e3e905), S21) + b;
|
||||
d = rotateLeft((d + G(a, b, c) + X[ 2] + 0xfcefa3f8), S22) + a;
|
||||
c = rotateLeft((c + G(d, a, b) + X[ 7] + 0x676f02d9), S23) + d;
|
||||
b = rotateLeft((b + G(c, d, a) + X[12] + 0x8d2a4c8a), S24) + c;
|
||||
|
||||
//
|
||||
// Round 3 - H cycle, 16 times.
|
||||
//
|
||||
a = rotateLeft((a + H(b, c, d) + X[ 5] + 0xfffa3942), S31) + b;
|
||||
d = rotateLeft((d + H(a, b, c) + X[ 8] + 0x8771f681), S32) + a;
|
||||
c = rotateLeft((c + H(d, a, b) + X[11] + 0x6d9d6122), S33) + d;
|
||||
b = rotateLeft((b + H(c, d, a) + X[14] + 0xfde5380c), S34) + c;
|
||||
a = rotateLeft((a + H(b, c, d) + X[ 1] + 0xa4beea44), S31) + b;
|
||||
d = rotateLeft((d + H(a, b, c) + X[ 4] + 0x4bdecfa9), S32) + a;
|
||||
c = rotateLeft((c + H(d, a, b) + X[ 7] + 0xf6bb4b60), S33) + d;
|
||||
b = rotateLeft((b + H(c, d, a) + X[10] + 0xbebfbc70), S34) + c;
|
||||
a = rotateLeft((a + H(b, c, d) + X[13] + 0x289b7ec6), S31) + b;
|
||||
d = rotateLeft((d + H(a, b, c) + X[ 0] + 0xeaa127fa), S32) + a;
|
||||
c = rotateLeft((c + H(d, a, b) + X[ 3] + 0xd4ef3085), S33) + d;
|
||||
b = rotateLeft((b + H(c, d, a) + X[ 6] + 0x04881d05), S34) + c;
|
||||
a = rotateLeft((a + H(b, c, d) + X[ 9] + 0xd9d4d039), S31) + b;
|
||||
d = rotateLeft((d + H(a, b, c) + X[12] + 0xe6db99e5), S32) + a;
|
||||
c = rotateLeft((c + H(d, a, b) + X[15] + 0x1fa27cf8), S33) + d;
|
||||
b = rotateLeft((b + H(c, d, a) + X[ 2] + 0xc4ac5665), S34) + c;
|
||||
|
||||
//
|
||||
// Round 4 - K cycle, 16 times.
|
||||
//
|
||||
a = rotateLeft((a + K(b, c, d) + X[ 0] + 0xf4292244), S41) + b;
|
||||
d = rotateLeft((d + K(a, b, c) + X[ 7] + 0x432aff97), S42) + a;
|
||||
c = rotateLeft((c + K(d, a, b) + X[14] + 0xab9423a7), S43) + d;
|
||||
b = rotateLeft((b + K(c, d, a) + X[ 5] + 0xfc93a039), S44) + c;
|
||||
a = rotateLeft((a + K(b, c, d) + X[12] + 0x655b59c3), S41) + b;
|
||||
d = rotateLeft((d + K(a, b, c) + X[ 3] + 0x8f0ccc92), S42) + a;
|
||||
c = rotateLeft((c + K(d, a, b) + X[10] + 0xffeff47d), S43) + d;
|
||||
b = rotateLeft((b + K(c, d, a) + X[ 1] + 0x85845dd1), S44) + c;
|
||||
a = rotateLeft((a + K(b, c, d) + X[ 8] + 0x6fa87e4f), S41) + b;
|
||||
d = rotateLeft((d + K(a, b, c) + X[15] + 0xfe2ce6e0), S42) + a;
|
||||
c = rotateLeft((c + K(d, a, b) + X[ 6] + 0xa3014314), S43) + d;
|
||||
b = rotateLeft((b + K(c, d, a) + X[13] + 0x4e0811a1), S44) + c;
|
||||
a = rotateLeft((a + K(b, c, d) + X[ 4] + 0xf7537e82), S41) + b;
|
||||
d = rotateLeft((d + K(a, b, c) + X[11] + 0xbd3af235), S42) + a;
|
||||
c = rotateLeft((c + K(d, a, b) + X[ 2] + 0x2ad7d2bb), S43) + d;
|
||||
b = rotateLeft((b + K(c, d, a) + X[ 9] + 0xeb86d391), S44) + c;
|
||||
|
||||
H1 += a;
|
||||
H2 += b;
|
||||
H3 += c;
|
||||
H4 += d;
|
||||
|
||||
//
|
||||
// reset the offset and clean out the word buffer.
|
||||
//
|
||||
xOff = 0;
|
||||
for (int i = 0; i != X.length; i++)
|
||||
{
|
||||
X[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -37,10 +37,11 @@ import java.util.Properties;
|
||||
public class HMACSHA256Bench {
|
||||
public static void main(String args[]) {
|
||||
runTest(new I2PAppContext());
|
||||
System.out.println("Running as MD5");
|
||||
Properties props = new Properties();
|
||||
props.setProperty("i2p.fakeHMAC", "true");
|
||||
//props.setProperty("i2p.fakeHMAC", "true");
|
||||
props.setProperty("i2p.HMACMD5", "true");
|
||||
runTest(new I2PAppContext(props));
|
||||
|
||||
}
|
||||
private static void runTest(I2PAppContext ctx) {
|
||||
SessionKey key = ctx.keyGenerator().generateSessionKey();
|
||||
@ -109,7 +110,7 @@ public class HMACSHA256Bench {
|
||||
private static void display(int times, long before, long after, int len, String name) {
|
||||
double rate = ((double)times)/(((double)after-(double)before)/1000.0d);
|
||||
double kbps = ((double)len/1024.0d)*((double)times)/(((double)after-(double)before)/1000.0d);
|
||||
System.out.println(name + " HMAC-SHA256 pulled " + kbps + "KBps or " + rate + " calcs per second");
|
||||
System.out.println(name + " HMAC pulled " + kbps + "KBps or " + rate + " calcs per second");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,10 @@
|
||||
$Id: history.txt,v 1.206 2005/05/25 16:32:38 duck Exp $
|
||||
$Id: history.txt,v 1.207 2005/07/04 15:44:17 jrandom Exp $
|
||||
|
||||
2005-07-05
|
||||
* Use a buffered PRNG, pulling the PRNG data off a larger precalculated
|
||||
buffer, rather than the underlying PRNG's (likely small) one, which in
|
||||
turn reduces the frequency of recalcing.
|
||||
* More tuning to reduce temporary allocation churn
|
||||
|
||||
2005-07-04 jrandom
|
||||
* Within the tunnel, use xor(IV, msg[0:16]) as the flag to detect dups,
|
||||
|
@ -22,7 +22,8 @@ import net.i2p.util.Log;
|
||||
*/
|
||||
public class TunnelDataMessage extends I2NPMessageImpl {
|
||||
private Log _log;
|
||||
private TunnelId _tunnelId;
|
||||
private long _tunnelId;
|
||||
private TunnelId _tunnelIdObj;
|
||||
private byte[] _data;
|
||||
|
||||
public final static int MESSAGE_TYPE = 18;
|
||||
@ -48,8 +49,17 @@ public class TunnelDataMessage extends I2NPMessageImpl {
|
||||
setMessageExpiration(context.clock().now() + EXPIRATION_PERIOD);
|
||||
}
|
||||
|
||||
public TunnelId getTunnelId() { return _tunnelId; }
|
||||
public void setTunnelId(TunnelId id) { _tunnelId = id; }
|
||||
public long getTunnelId() { return _tunnelId; }
|
||||
public void setTunnelId(long id) { _tunnelId = id; }
|
||||
public TunnelId getTunnelIdObj() {
|
||||
if (_tunnelIdObj == null)
|
||||
_tunnelIdObj = new TunnelId(_tunnelId); // not thread safe, but immutable, so who cares
|
||||
return _tunnelIdObj;
|
||||
}
|
||||
public void setTunnelId(TunnelId id) {
|
||||
_tunnelIdObj = id;
|
||||
_tunnelId = id.getTunnelId();
|
||||
}
|
||||
|
||||
public byte[] getData() { return _data; }
|
||||
public void setData(byte data[]) {
|
||||
@ -62,10 +72,10 @@ public class TunnelDataMessage extends I2NPMessageImpl {
|
||||
if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
|
||||
int curIndex = offset;
|
||||
|
||||
_tunnelId = new TunnelId(DataHelper.fromLong(data, curIndex, 4));
|
||||
_tunnelId = DataHelper.fromLong(data, curIndex, 4);
|
||||
curIndex += 4;
|
||||
|
||||
if (_tunnelId.getTunnelId() <= 0)
|
||||
if (_tunnelId <= 0)
|
||||
throw new I2NPMessageException("Invalid tunnel Id " + _tunnelId);
|
||||
|
||||
// we cant cache it in trivial form, as other components (e.g. HopProcessor)
|
||||
@ -82,12 +92,12 @@ public class TunnelDataMessage extends I2NPMessageImpl {
|
||||
protected int calculateWrittenLength() { return 4 + DATA_SIZE; }
|
||||
/** write the message body to the output array, starting at the given index */
|
||||
protected int writeMessageBody(byte out[], int curIndex) throws I2NPMessageException {
|
||||
if ( (_tunnelId == null) || (_data == null) )
|
||||
if ( (_tunnelId <= 0) || (_data == null) )
|
||||
throw new I2NPMessageException("Not enough data to write out (id=" + _tunnelId + " data=" + _data + ")");
|
||||
if (_data.length <= 0)
|
||||
throw new I2NPMessageException("Not enough data to write out (data.length=" + _data.length + ")");
|
||||
|
||||
DataHelper.toLong(out, curIndex, 4, _tunnelId.getTunnelId());
|
||||
DataHelper.toLong(out, curIndex, 4, _tunnelId);
|
||||
curIndex += 4;
|
||||
System.arraycopy(_data, 0, out, curIndex, DATA_SIZE);
|
||||
curIndex += _data.length;
|
||||
@ -99,7 +109,7 @@ public class TunnelDataMessage extends I2NPMessageImpl {
|
||||
public int getType() { return MESSAGE_TYPE; }
|
||||
|
||||
public int hashCode() {
|
||||
return DataHelper.hashCode(getTunnelId()) +
|
||||
return (int)_tunnelId +
|
||||
DataHelper.hashCode(_data);
|
||||
}
|
||||
|
||||
|
@ -219,6 +219,11 @@ public class MessageHistory {
|
||||
addEntry(getPrefix() + "message " + messageId + " on tunnel " + tunnelId + " / " + toTunnel + " as " + type);
|
||||
}
|
||||
|
||||
public void tunnelDispatched(long messageId, long innerMessageId, long tunnelId, String type) {
|
||||
if (!_doLog) return;
|
||||
addEntry(getPrefix() + "message " + messageId + "/" + innerMessageId + " on " + tunnelId + " as " + type);
|
||||
}
|
||||
|
||||
/**
|
||||
* The local router has detected a failure in the given tunnel
|
||||
*
|
||||
@ -472,13 +477,14 @@ public class MessageHistory {
|
||||
buf.append("Break message ").append(messageId).append(" into fragments: ").append(numFragments);
|
||||
addEntry(buf.toString());
|
||||
}
|
||||
public void fragmentMessage(long messageId, int numFragments, String tunnel) {
|
||||
public void fragmentMessage(long messageId, int numFragments, Object tunnel) {
|
||||
if (!_doLog) return;
|
||||
if (messageId == -1) throw new IllegalArgumentException("why are you -1?");
|
||||
StringBuffer buf = new StringBuffer(48);
|
||||
buf.append(getPrefix());
|
||||
buf.append("Break message ").append(messageId).append(" into fragments: ").append(numFragments);
|
||||
buf.append(" on ").append(tunnel);
|
||||
if (tunnel != null)
|
||||
buf.append(" on ").append(tunnel.toString());
|
||||
addEntry(buf.toString());
|
||||
}
|
||||
public void droppedTunnelDataMessageUnknown(long msgId, long tunnelId) {
|
||||
|
@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
|
||||
*
|
||||
*/
|
||||
public class RouterVersion {
|
||||
public final static String ID = "$Revision: 1.197 $ $Date: 2005/05/25 16:32:38 $";
|
||||
public final static String ID = "$Revision: 1.198 $ $Date: 2005/07/04 15:44:21 $";
|
||||
public final static String VERSION = "0.5.0.7";
|
||||
public final static long BUILD = 9;
|
||||
public final static long BUILD = 10;
|
||||
public static void main(String args[]) {
|
||||
System.out.println("I2P Router version: " + VERSION);
|
||||
System.out.println("Router ID: " + RouterVersion.ID);
|
||||
|
@ -61,6 +61,9 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
|
||||
public TransportBid getBid(OutNetMessage msg) {
|
||||
return _manager.getBid(msg);
|
||||
}
|
||||
public TransportBid getNextBid(OutNetMessage msg) {
|
||||
return _manager.getNextBid(msg);
|
||||
}
|
||||
|
||||
public void processMessage(OutNetMessage msg) {
|
||||
//GetBidsJob j = new GetBidsJob(_context, this, msg);
|
||||
|
@ -59,28 +59,13 @@ public class GetBidsJob extends JobImpl {
|
||||
return;
|
||||
}
|
||||
|
||||
List bids = facade.getBids(msg);
|
||||
|
||||
if ( (bids == null) || (bids.size() <= 0) ) {
|
||||
context.shitlist().shitlistRouter(to, "No bids after " + (bids != null ? bids.size() + " tries" : "0 tries"));
|
||||
TransportBid bid = facade.getNextBid(msg);
|
||||
if (bid == null) {
|
||||
context.shitlist().shitlistRouter(to, "No more bids available");
|
||||
context.netDb().fail(to);
|
||||
fail(context, msg);
|
||||
} else {
|
||||
int lowestCost = -1;
|
||||
TransportBid winner = null;
|
||||
for (int i = 0; i < bids.size(); i++) {
|
||||
TransportBid bid = (TransportBid)bids.get(i);
|
||||
if ( (lowestCost < 0) || (bid.getLatencyMs() < lowestCost) ) {
|
||||
winner = bid;
|
||||
lowestCost = bid.getLatencyMs();
|
||||
}
|
||||
}
|
||||
if (winner != null) {
|
||||
if (log.shouldLog(Log.INFO))
|
||||
log.info("Winning bid: " + winner + " out of " + bids);
|
||||
|
||||
winner.getTransport().send(msg);
|
||||
}
|
||||
bid.getTransport().send(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,6 +159,33 @@ public class TransportManager implements TransportEventListener {
|
||||
return rv;
|
||||
}
|
||||
|
||||
public TransportBid getNextBid(OutNetMessage msg) {
|
||||
Set failedTransports = msg.getFailedTransports();
|
||||
TransportBid rv = null;
|
||||
for (int i = 0; i < _transports.size(); i++) {
|
||||
Transport t = (Transport)_transports.get(i);
|
||||
if (failedTransports.contains(t.getStyle())) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Skipping transport " + t.getStyle() + " as it already failed");
|
||||
continue;
|
||||
}
|
||||
// we always want to try all transports, in case there is a faster bidirectional one
|
||||
// already connected (e.g. peer only has a public PHTTP address, but they've connected
|
||||
// to us via TCP, send via TCP)
|
||||
TransportBid bid = t.bid(msg.getTarget(), msg.getMessageSize());
|
||||
if (bid != null) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Transport " + t.getStyle() + " bid: " + bid);
|
||||
if ( (rv == null) || (rv.getLatencyMs() > bid.getLatencyMs()) )
|
||||
rv = bid;
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Transport " + t.getStyle() + " did not produce a bid");
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public void messageReceived(I2NPMessage message, RouterIdentity fromRouter, Hash fromRouterHash) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("I2NPMessage received: " + message.getClass().getName(), new Exception("Where did I come from again?"));
|
||||
|
@ -101,7 +101,7 @@ public class ACKSender implements Runnable {
|
||||
_context.statManager().addRateData("udp.sendACKRemaining", remaining, 0);
|
||||
now = _context.clock().now();
|
||||
_context.statManager().addRateData("udp.ackFrequency", now-lastSend, now-wanted);
|
||||
_context.statManager().getStatLog().addData(peer.getRemoteHostId().toString(), "udp.peer.sendACKCount", ackBitfields.size(), 0);
|
||||
//_context.statManager().getStatLog().addData(peer.getRemoteHostId().toString(), "udp.peer.sendACKCount", ackBitfields.size(), 0);
|
||||
UDPPacket ack = _builder.buildACK(peer, ackBitfields);
|
||||
ack.markType(1);
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
|
@ -34,7 +34,7 @@ public class OutboundMessageState {
|
||||
private int _nextSendFragment;
|
||||
|
||||
public static final int MAX_FRAGMENTS = 32;
|
||||
private static final ByteCache _cache = ByteCache.getInstance(64, MAX_FRAGMENTS*1024);
|
||||
private static final ByteCache _cache = ByteCache.getInstance(128, MAX_FRAGMENTS*1024);
|
||||
|
||||
public OutboundMessageState(I2PAppContext context) {
|
||||
_context = context;
|
||||
|
@ -27,6 +27,7 @@ public class PacketBuilder {
|
||||
private Log _log;
|
||||
|
||||
private static final ByteCache _ivCache = ByteCache.getInstance(64, UDPPacket.IV_SIZE);
|
||||
private static final ByteCache _hmacCache = ByteCache.getInstance(64, Hash.HASH_LENGTH);
|
||||
|
||||
public PacketBuilder(I2PAppContext ctx) {
|
||||
_context = ctx;
|
||||
@ -482,16 +483,20 @@ public class PacketBuilder {
|
||||
|
||||
int hmacOff = packet.getPacket().getOffset();
|
||||
int hmacLen = encryptSize + UDPPacket.IV_SIZE + 2;
|
||||
Hash hmac = _context.hmac().calculate(macKey, data, hmacOff, hmacLen);
|
||||
//Hash hmac = _context.hmac().calculate(macKey, data, hmacOff, hmacLen);
|
||||
ByteArray ba = _hmacCache.acquire();
|
||||
_context.hmac().calculate(macKey, data, hmacOff, hmacLen, ba.getData(), 0);
|
||||
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Authenticating " + packet.getPacketDataLength() + // packet.getPacket().getLength() +
|
||||
"\nIV: " + Base64.encode(iv.getData()) +
|
||||
"\nraw mac: " + hmac.toBase64() +
|
||||
"\nraw mac: " + Base64.encode(ba.getData()) +
|
||||
"\nMAC key: " + macKey.toBase64());
|
||||
// ok, now lets put it back where it belongs...
|
||||
System.arraycopy(data, hmacOff, data, encryptOffset, encryptSize);
|
||||
System.arraycopy(hmac.getData(), 0, data, hmacOff, UDPPacket.MAC_SIZE);
|
||||
//System.arraycopy(hmac.getData(), 0, data, hmacOff, UDPPacket.MAC_SIZE);
|
||||
System.arraycopy(ba.getData(), 0, data, hmacOff, UDPPacket.MAC_SIZE);
|
||||
System.arraycopy(iv.getData(), 0, data, hmacOff + UDPPacket.MAC_SIZE, UDPPacket.IV_SIZE);
|
||||
_hmacCache.release(ba);
|
||||
}
|
||||
}
|
||||
|
@ -68,9 +68,9 @@ public class UDPPacket {
|
||||
public static final byte BITFIELD_CONTINUATION = (byte)(1 << 7);
|
||||
|
||||
private static final int MAX_VALIDATE_SIZE = MAX_PACKET_SIZE;
|
||||
private static final ByteCache _validateCache = ByteCache.getInstance(16, MAX_VALIDATE_SIZE);
|
||||
private static final ByteCache _ivCache = ByteCache.getInstance(16, IV_SIZE);
|
||||
private static final ByteCache _dataCache = ByteCache.getInstance(64, MAX_PACKET_SIZE);
|
||||
private static final ByteCache _validateCache = ByteCache.getInstance(64, MAX_VALIDATE_SIZE);
|
||||
private static final ByteCache _ivCache = ByteCache.getInstance(64, IV_SIZE);
|
||||
private static final ByteCache _dataCache = ByteCache.getInstance(128, MAX_PACKET_SIZE);
|
||||
|
||||
private UDPPacket(I2PAppContext ctx) {
|
||||
_context = ctx;
|
||||
@ -237,8 +237,11 @@ public class UDPPacket {
|
||||
_released = true;
|
||||
//_releasedBy = new Exception("released by");
|
||||
//_acquiredBy = null;
|
||||
//_dataCache.release(_dataBuf);
|
||||
if (!CACHE) return;
|
||||
//
|
||||
if (!CACHE) {
|
||||
_dataCache.release(_dataBuf);
|
||||
return;
|
||||
}
|
||||
synchronized (_packetCache) {
|
||||
if (_packetCache.size() <= 64) {
|
||||
_packetCache.add(this);
|
||||
|
@ -57,8 +57,8 @@ public class BatchedRouterPreprocessor extends BatchedPreprocessor {
|
||||
|
||||
protected void notePreprocessing(long messageId, int numFragments) {
|
||||
if (_config != null)
|
||||
_routerContext.messageHistory().fragmentMessage(messageId, numFragments, _config.toString());
|
||||
_routerContext.messageHistory().fragmentMessage(messageId, numFragments, _config);
|
||||
else
|
||||
_routerContext.messageHistory().fragmentMessage(messageId, numFragments, _hopConfig.toString());
|
||||
_routerContext.messageHistory().fragmentMessage(messageId, numFragments, _hopConfig);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ public class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
|
||||
protected static final int IV_SIZE = HopProcessor.IV_LENGTH;
|
||||
protected static final ByteCache _dataCache = ByteCache.getInstance(512, PREPROCESSED_SIZE);
|
||||
protected static final ByteCache _ivCache = ByteCache.getInstance(128, IV_SIZE);
|
||||
protected static final ByteCache _hashCache = ByteCache.getInstance(128, Hash.HASH_LENGTH);
|
||||
|
||||
public TrivialPreprocessor(I2PAppContext ctx) {
|
||||
_context = ctx;
|
||||
@ -104,7 +105,11 @@ public class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
|
||||
|
||||
// payload ready, now H(instructions+payload+IV)
|
||||
System.arraycopy(iv, 0, fragments, fragmentLength, IV_SIZE);
|
||||
Hash h = _context.sha().calculateHash(fragments, 0, fragmentLength + IV_SIZE);
|
||||
|
||||
ByteArray hashBuf = _hashCache.acquire();
|
||||
//Hash h = _context.sha().calculateHash(fragments, 0, fragmentLength + IV_SIZE);
|
||||
_context.sha().calculateHash(fragments, 0, fragmentLength + IV_SIZE, hashBuf.getData(), 0);
|
||||
|
||||
//Hash h = _context.sha().calculateHash(target, 0, offset + IV_SIZE);
|
||||
//_log.debug("before shift: " + Base64.encode(target));
|
||||
// now shiiiiiift
|
||||
@ -121,10 +126,12 @@ public class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
|
||||
int offset = 0;
|
||||
System.arraycopy(iv, 0, fragments, offset, IV_SIZE);
|
||||
offset += IV_SIZE;
|
||||
System.arraycopy(h.getData(), 0, fragments, offset, 4);
|
||||
//System.arraycopy(h.getData(), 0, fragments, offset, 4);
|
||||
System.arraycopy(hashBuf.getData(), 0, fragments, offset, 4);
|
||||
offset += 4;
|
||||
//_log.debug("before pad : " + Base64.encode(target));
|
||||
|
||||
_hashCache.release(hashBuf);
|
||||
_ivCache.release(ivBuf);
|
||||
|
||||
// fits in a single message, so may be smaller than the full size
|
||||
|
@ -349,35 +349,35 @@ public class TunnelDispatcher implements Service {
|
||||
long before = _context.clock().now();
|
||||
TunnelParticipant participant = null;
|
||||
synchronized (_participants) {
|
||||
participant = (TunnelParticipant)_participants.get(msg.getTunnelId());
|
||||
participant = (TunnelParticipant)_participants.get(msg.getTunnelIdObj());
|
||||
}
|
||||
if (participant != null) {
|
||||
// we are either just a random participant or the inbound endpoint
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("dispatch to participant " + participant + ": " + msg.getUniqueId() + " from "
|
||||
+ recvFrom.toBase64().substring(0,4));
|
||||
_context.messageHistory().tunnelDispatched(msg.getUniqueId(), msg.getTunnelId().getTunnelId(), "participant");
|
||||
_context.messageHistory().tunnelDispatched(msg.getUniqueId(), msg.getTunnelId(), "participant");
|
||||
participant.dispatch(msg, recvFrom);
|
||||
_context.statManager().addRateData("tunnel.dispatchParticipant", 1, 0);
|
||||
} else {
|
||||
OutboundTunnelEndpoint endpoint = null;
|
||||
synchronized (_outboundEndpoints) {
|
||||
endpoint = (OutboundTunnelEndpoint)_outboundEndpoints.get(msg.getTunnelId());
|
||||
endpoint = (OutboundTunnelEndpoint)_outboundEndpoints.get(msg.getTunnelIdObj());
|
||||
}
|
||||
if (endpoint != null) {
|
||||
// we are the outobund endpoint
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("dispatch where we are the outbound endpoint: " + endpoint + ": "
|
||||
+ msg + " from " + recvFrom.toBase64().substring(0,4));
|
||||
_context.messageHistory().tunnelDispatched(msg.getUniqueId(), msg.getTunnelId().getTunnelId(), "outbound endpoint");
|
||||
_context.messageHistory().tunnelDispatched(msg.getUniqueId(), msg.getTunnelId(), "outbound endpoint");
|
||||
endpoint.dispatch(msg, recvFrom);
|
||||
|
||||
_context.statManager().addRateData("tunnel.dispatchEndpoint", 1, 0);
|
||||
} else {
|
||||
_context.messageHistory().droppedTunnelDataMessageUnknown(msg.getUniqueId(), msg.getTunnelId().getTunnelId());
|
||||
_context.messageHistory().droppedTunnelDataMessageUnknown(msg.getUniqueId(), msg.getTunnelId());
|
||||
int level = (_context.router().getUptime() > 10*60*1000 ? Log.ERROR : Log.WARN);
|
||||
if (_log.shouldLog(level))
|
||||
_log.log(level, "no matching participant/endpoint for id=" + msg.getTunnelId().getTunnelId()
|
||||
_log.log(level, "no matching participant/endpoint for id=" + msg.getTunnelId()
|
||||
+ " expiring in " + DataHelper.formatDuration(msg.getMessageExpiration()-_context.clock().now())
|
||||
+ ": existing = " + _participants.size() + " / " + _outboundEndpoints.size());
|
||||
}
|
||||
@ -410,8 +410,9 @@ public class TunnelDispatcher implements Service {
|
||||
+ msg.getMessage().getClass().getName());
|
||||
return;
|
||||
}
|
||||
_context.messageHistory().tunnelDispatched("message " + msg.getUniqueId() + "/" + msg.getMessage().getUniqueId() + " on tunnel "
|
||||
+ msg.getTunnelId().getTunnelId() + " as inbound gateway");
|
||||
//_context.messageHistory().tunnelDispatched("message " + msg.getUniqueId() + "/" + msg.getMessage().getUniqueId() + " on tunnel "
|
||||
// + msg.getTunnelId().getTunnelId() + " as inbound gateway");
|
||||
_context.messageHistory().tunnelDispatched(msg.getUniqueId(), msg.getMessage().getUniqueId(), msg.getTunnelId().getTunnelId(), "inbound gateway");
|
||||
gw.add(msg);
|
||||
_context.statManager().addRateData("tunnel.dispatchInbound", 1, 0);
|
||||
} else {
|
||||
|
@ -104,7 +104,7 @@ public class RequestTunnelJob extends JobImpl {
|
||||
// inbound tunnel, which means we are the first person asked, and if
|
||||
// it is a zero hop tunnel, then we are also the last person asked
|
||||
|
||||
long id = getContext().random().nextLong(TunnelId.MAX_ID_VALUE);
|
||||
long id = getContext().random().nextLong(TunnelId.MAX_ID_VALUE-1) + 1;
|
||||
_currentConfig.setReceiveTunnelId(DataHelper.toLong(4, id));
|
||||
if (_config.getLength() > 1) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
|
Reference in New Issue
Block a user