the following isn't the end of the 0.4.1 updates, as there are still more things left to clean

up and debug in the new tcp transport, but it all works, and i dont like having big changes
sitting on my local machine (and there's no real need for branching atm)
2004-09-26  jrandom
    * Complete rewrite of the TCP transport with IP autodetection and
      low CPU overhead reconnections.  More concise connectivity errors
      are listed on the /oldconsole.jsp as well.  The IP autodetection works
      by listening to the first person who tells you what your IP address is
      when you have not defined one yourself and you have no other TCP
      connections.
    * Update to the I2NP message format to add transparent verification at
      the I2NP level (beyond standard TCP verification).
    * Remove a potential weakness in our AESEngine's safeEncrypt and safeDecrypt
      implementation (rather than verifying with E(H(key)), we now verify with
      E(H(iv))).
    * The above changes are NOT BACKWARDS COMPATIBLE.
    * Removed all of the old unused PHTTP code.
    * Refactor various methods and clean up some javadoc.
This commit is contained in:
jrandom
2004-09-26 15:16:44 +00:00
committed by zzz
parent 4c29c20613
commit b67b243ebd
26 changed files with 2885 additions and 2236 deletions

View File

@ -58,7 +58,7 @@ public class AESEngine {
if ((iv == null) || (payload == null) || (sessionKey == null) || (iv.length != 16)) return null;
ByteArrayOutputStream baos = new ByteArrayOutputStream(paddedSize + 64);
Hash h = _context.sha().calculateHash(sessionKey.getData());
Hash h = _context.sha().calculateHash(iv);
try {
h.writeBytes(baos);
DataHelper.writeLong(baos, 4, payload.length);
@ -84,7 +84,7 @@ public class AESEngine {
return null;
}
ByteArrayInputStream bais = new ByteArrayInputStream(decr);
Hash h = _context.sha().calculateHash(sessionKey.getData());
Hash h = _context.sha().calculateHash(iv);
try {
Hash rh = new Hash();
rh.readBytes(bais);

View File

@ -13,8 +13,13 @@ import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import net.i2p.I2PAppContext;
import net.i2p.data.ByteArray;
import net.i2p.data.DataHelper;
import net.i2p.data.SessionKey;
import net.i2p.util.Clock;
import net.i2p.util.I2PThread;
@ -135,7 +140,62 @@ public class DHSessionKeyBuilder {
_sessionKey = null;
_extraExchangedBytes = new ByteArray();
}
/**
* Conduct a DH exchange over the streams, returning the resulting data.
*
* @return exchanged data
* @throws IOException if there is an error (but does not close the streams
*/
public static DHSessionKeyBuilder exchangeKeys(InputStream in, OutputStream out) throws IOException {
DHSessionKeyBuilder builder = new DHSessionKeyBuilder();
// send: X
writeBigI(out, builder.getMyPublicValue());
// read: Y
BigInteger Y = readBigI(in);
if (Y == null) return null;
builder.setPeerPublicValue(Y);
return builder;
}
static BigInteger readBigI(InputStream in) throws IOException {
byte Y[] = new byte[256];
int read = DataHelper.read(in, Y);
if (read != 256) {
return null;
}
if (1 == (Y[0] & 0x80)) {
// high bit set, need to inject an additional byte to keep 2s complement
if (_log.shouldLog(Log.DEBUG))
_log.debug("High bit set");
byte Y2[] = new byte[257];
System.arraycopy(Y, 0, Y2, 1, 256);
Y = Y2;
}
return new NativeBigInteger(Y);
}
/**
* Write out the integer as a 256 byte value. This left pads with 0s so
* to keep in 2s complement, and if it is already 257 bytes (due to
* the sign bit) ignore that first byte.
*/
static void writeBigI(OutputStream out, BigInteger val) throws IOException {
byte x[] = val.toByteArray();
for (int i = x.length; i < 256; i++)
out.write(0);
if (x.length == 257)
out.write(x, 1, 256);
else if (x.length == 256)
out.write(x);
else if (x.length > 257)
throw new IllegalArgumentException("Value is too large! length="+x.length);
out.flush();
}
private static final int getSize() {
synchronized (_builders) {
return _builders.size();

View File

@ -99,24 +99,28 @@ public class DataHelper {
*/
public static void writeProperties(OutputStream rawStream, Properties props)
throws DataFormatException, IOException {
OrderedProperties p = new OrderedProperties();
if (props != null) p.putAll(props);
ByteArrayOutputStream baos = new ByteArrayOutputStream(32);
for (Iterator iter = p.keySet().iterator(); iter.hasNext();) {
String key = (String) iter.next();
String val = p.getProperty(key);
// now make sure they're in UTF-8
//key = new String(key.getBytes(), "UTF-8");
//val = new String(val.getBytes(), "UTF-8");
writeString(baos, key);
baos.write(_equalBytes);
writeString(baos, val);
baos.write(_semicolonBytes);
if (props != null) {
OrderedProperties p = new OrderedProperties();
p.putAll(props);
ByteArrayOutputStream baos = new ByteArrayOutputStream(32);
for (Iterator iter = p.keySet().iterator(); iter.hasNext();) {
String key = (String) iter.next();
String val = p.getProperty(key);
// now make sure they're in UTF-8
//key = new String(key.getBytes(), "UTF-8");
//val = new String(val.getBytes(), "UTF-8");
writeString(baos, key);
baos.write(_equalBytes);
writeString(baos, val);
baos.write(_semicolonBytes);
}
baos.close();
byte propBytes[] = baos.toByteArray();
writeLong(rawStream, 2, propBytes.length);
rawStream.write(propBytes);
} else {
writeLong(rawStream, 2, 0);
}
baos.close();
byte propBytes[] = baos.toByteArray();
writeLong(rawStream, 2, propBytes.length);
rawStream.write(propBytes);
}
/**

View File

@ -322,6 +322,22 @@ public class RouterInfo extends DataStructureImpl {
return true;
}
/**
* Pull the first workable target address for the given transport
*
*/
public RouterAddress getTargetAddress(String transportStyle) {
synchronized (_addresses) {
for (Iterator iter = _addresses.iterator(); iter.hasNext(); ) {
RouterAddress addr = (RouterAddress)iter.next();
if (addr.getTransportStyle().equals(transportStyle))
return addr;
}
}
return null;
}
/**
* Actually validate the signature