diff --git a/core/java/src/net/i2p/crypto/DSAEngine.java b/core/java/src/net/i2p/crypto/DSAEngine.java index 7c8758185..7a1f95ecb 100644 --- a/core/java/src/net/i2p/crypto/DSAEngine.java +++ b/core/java/src/net/i2p/crypto/DSAEngine.java @@ -50,8 +50,10 @@ public class DSAEngine { public static DSAEngine getInstance() { return I2PAppContext.getGlobalContext().dsa(); } - public boolean verifySignature(Signature signature, byte signedData[], SigningPublicKey verifyingKey) { + return verifySignature(signature, signedData, 0, signedData.length, verifyingKey); + } + public boolean verifySignature(Signature signature, byte signedData[], int offset, int size, SigningPublicKey verifyingKey) { long start = _context.clock().now(); byte[] sigbytes = signature.getData(); @@ -68,7 +70,7 @@ public class DSAEngine { BigInteger r = new NativeBigInteger(1, rbytes); BigInteger y = new NativeBigInteger(1, verifyingKey.getData()); BigInteger w = s.modInverse(CryptoConstants.dsaq); - byte data[] = calculateHash(signedData).getData(); + byte data[] = calculateHash(signedData, offset, size).getData(); NativeBigInteger bi = new NativeBigInteger(1, data); BigInteger u1 = bi.multiply(w).mod(CryptoConstants.dsaq); BigInteger u2 = r.multiply(w).mod(CryptoConstants.dsaq); @@ -88,6 +90,9 @@ public class DSAEngine { } public Signature sign(byte data[], SigningPrivateKey signingKey) { + return sign(data, 0, data.length, signingKey); + } + public Signature sign(byte data[], int offset, int length, SigningPrivateKey signingKey) { if ((signingKey == null) || (data == null) || (data.length <= 0)) return null; long start = _context.clock().now(); @@ -100,7 +105,7 @@ public class DSAEngine { BigInteger r = CryptoConstants.dsag.modPow(k, CryptoConstants.dsap).mod(CryptoConstants.dsaq); BigInteger kinv = k.modInverse(CryptoConstants.dsaq); - Hash h = calculateHash(data); + Hash h = calculateHash(data, offset, length); if (h == null) return null; @@ -150,42 +155,42 @@ public class DSAEngine { private int[] H0 = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0}; - private Hash calculateHash(byte[] source) { - long length = source.length * 8; + private Hash calculateHash(byte[] source, int offset, int len) { + long length = len * 8; int k = 448 - (int) ((length + 1) % 512); if (k < 0) { k += 512; } int padbytes = k / 8; - int wordlength = source.length / 4 + padbytes / 4 + 3; + int wordlength = len / 4 + padbytes / 4 + 3; int[] M0 = new int[wordlength]; int wordcount = 0; int x = 0; - for (x = 0; x < (source.length / 4) * 4; x += 4) { - M0[wordcount] = source[x] << 24 >>> 24 << 24; - M0[wordcount] |= source[x + 1] << 24 >>> 24 << 16; - M0[wordcount] |= source[x + 2] << 24 >>> 24 << 8; - M0[wordcount] |= source[x + 3] << 24 >>> 24 << 0; + for (x = 0; x < (len / 4) * 4; x += 4) { + M0[wordcount] = source[offset + x] << 24 >>> 24 << 24; + M0[wordcount] |= source[offset + x + 1] << 24 >>> 24 << 16; + M0[wordcount] |= source[offset + x + 2] << 24 >>> 24 << 8; + M0[wordcount] |= source[offset + x + 3] << 24 >>> 24 << 0; wordcount++; } - switch (source.length - (wordcount + 1) * 4 + 4) { + switch (len - (wordcount + 1) * 4 + 4) { case 0: M0[wordcount] |= 0x80000000; break; case 1: - M0[wordcount] = source[x] << 24 >>> 24 << 24; + M0[wordcount] = source[offset + x] << 24 >>> 24 << 24; M0[wordcount] |= 0x00800000; break; case 2: - M0[wordcount] = source[x] << 24 >>> 24 << 24; - M0[wordcount] |= source[x + 1] << 24 >>> 24 << 16; + M0[wordcount] = source[offset + x] << 24 >>> 24 << 24; + M0[wordcount] |= source[offset + x + 1] << 24 >>> 24 << 16; M0[wordcount] |= 0x00008000; break; case 3: - M0[wordcount] = source[x] << 24 >>> 24 << 24; - M0[wordcount] |= source[x + 1] << 24 >>> 24 << 16; - M0[wordcount] |= source[x + 2] << 24 >>> 24 << 8; + M0[wordcount] = source[offset + x] << 24 >>> 24 << 24; + M0[wordcount] |= source[offset + x + 1] << 24 >>> 24 << 16; + M0[wordcount] |= source[offset + x + 2] << 24 >>> 24 << 8; M0[wordcount] |= 0x00000080; break; } diff --git a/core/java/src/net/i2p/data/Certificate.java b/core/java/src/net/i2p/data/Certificate.java index e2a4fd605..968ca1d4d 100644 --- a/core/java/src/net/i2p/data/Certificate.java +++ b/core/java/src/net/i2p/data/Certificate.java @@ -86,6 +86,41 @@ public class Certificate extends DataStructureImpl { DataHelper.writeLong(out, 2, 0L); } } + + + public int writeBytes(byte target[], int offset) { + int cur = offset; + DataHelper.toLong(target, cur, 1, _type); + cur++; + if (_payload != null) { + DataHelper.toLong(target, cur, 2, _payload.length); + cur += 2; + System.arraycopy(_payload, 0, target, cur, _payload.length); + cur += _payload.length; + } else { + DataHelper.toLong(target, cur, 2, 0); + cur += 2; + } + return cur - offset; + } + + public int readBytes(byte source[], int offset) { + int cur = offset; + _type = (int)DataHelper.fromLong(source, cur, 1); + cur++; + int length = (int)DataHelper.fromLong(source, cur, 2); + cur += 2; + if (length > 0) { + _payload = new byte[length]; + System.arraycopy(source, cur, _payload, 0, length); + cur += length; + } + return cur - offset; + } + + public int size() { + return 1 + 2 + (_payload != null ? _payload.length : 0); + } public boolean equals(Object object) { if ((object == null) || !(object instanceof Certificate)) return false; diff --git a/core/java/src/net/i2p/data/DataHelper.java b/core/java/src/net/i2p/data/DataHelper.java index 22e18a822..de04ae541 100644 --- a/core/java/src/net/i2p/data/DataHelper.java +++ b/core/java/src/net/i2p/data/DataHelper.java @@ -263,12 +263,16 @@ public class DataHelper { } public static byte[] toLong(int numBytes, long value) throws IllegalArgumentException { + byte val[] = new byte[numBytes]; + toLong(val, 0, numBytes, value); + return val; + } + + public static void toLong(byte target[], int offset, int numBytes, long value) throws IllegalArgumentException { if (numBytes <= 0) throw new IllegalArgumentException("Invalid number of bytes"); if (value < 0) throw new IllegalArgumentException("Negative value not allowed"); - byte val[] = new byte[numBytes]; for (int i = 0; i < numBytes; i++) - val[numBytes-i-1] = (byte)(value >>> (i*8)); - return val; + target[offset+numBytes-i-1] = (byte)(value >>> (i*8)); } public static long fromLong(byte src[], int offset, int numBytes) { diff --git a/core/java/src/net/i2p/data/Destination.java b/core/java/src/net/i2p/data/Destination.java index dac90bb37..d59097598 100644 --- a/core/java/src/net/i2p/data/Destination.java +++ b/core/java/src/net/i2p/data/Destination.java @@ -79,7 +79,41 @@ public class Destination extends DataStructureImpl { _signingKey.writeBytes(out); _certificate.writeBytes(out); } + + public int writeBytes(byte target[], int offset) { + int cur = offset; + System.arraycopy(_publicKey.getData(), 0, target, cur, PublicKey.KEYSIZE_BYTES); + cur += PublicKey.KEYSIZE_BYTES; + System.arraycopy(_signingKey.getData(), 0, target, cur, SigningPublicKey.KEYSIZE_BYTES); + cur += SigningPublicKey.KEYSIZE_BYTES; + cur += _certificate.writeBytes(target, cur); + return cur - offset; + } + + public int readBytes(byte source[], int offset) { + int cur = offset; + + _publicKey = new PublicKey(); + byte buf[] = new byte[PublicKey.KEYSIZE_BYTES]; + System.arraycopy(source, cur, buf, 0, PublicKey.KEYSIZE_BYTES); + _publicKey.setData(buf); + cur += PublicKey.KEYSIZE_BYTES; + + _signingKey = new SigningPublicKey(); + buf = new byte[SigningPublicKey.KEYSIZE_BYTES]; + System.arraycopy(source, cur, buf, 0, SigningPublicKey.KEYSIZE_BYTES); + cur += SigningPublicKey.KEYSIZE_BYTES; + + _certificate = new Certificate(); + cur += _certificate.readBytes(buf, cur); + + return cur - offset; + } + public int size() { + return PublicKey.KEYSIZE_BYTES + SigningPublicKey.KEYSIZE_BYTES + _certificate.size(); + } + public boolean equals(Object object) { if ((object == null) || !(object instanceof Destination)) return false; Destination dst = (Destination) object; diff --git a/history.txt b/history.txt index fdcd22b9b..c629c567c 100644 --- a/history.txt +++ b/history.txt @@ -1,4 +1,12 @@ -$Id: history.txt,v 1.49 2004/10/15 12:39:19 jrandom Exp $ +$Id: history.txt,v 1.50 2004/10/16 13:00:47 jrandom Exp $ + +2004-10-16 jrandom + * More aggressively fail peers if their tunnels are failing so that we + move off them quicker. + * Simplify some data structure serialization for reuse in the streaming + lib, as well as add support for signing and verifying partial byte + arrays. + * Logging updates 2004-10-16 jrandom * Increased the default minimum tunnel test time to 5 seconds, since we diff --git a/router/java/src/net/i2p/router/JobQueue.java b/router/java/src/net/i2p/router/JobQueue.java index 202c5ecc2..3c82164fa 100644 --- a/router/java/src/net/i2p/router/JobQueue.java +++ b/router/java/src/net/i2p/router/JobQueue.java @@ -302,6 +302,19 @@ public class JobQueue { } return when; } + /** + * When did the most recently begin job start? + */ + public long getLastJobEnd() { + long when = -1; + // not synchronized, so might b0rk if the runners are changed + for (Iterator iter = _queueRunners.values().iterator(); iter.hasNext(); ) { + long cur = ((JobQueueRunner)iter.next()).getLastEnd(); + if (cur > when) + cur = when; + } + return when; + } /** * retrieve the most recently begin and still currently active job, or null if * no jobs are running diff --git a/router/java/src/net/i2p/router/JobQueueRunner.java b/router/java/src/net/i2p/router/JobQueueRunner.java index 45d10c4d0..2c37821e7 100644 --- a/router/java/src/net/i2p/router/JobQueueRunner.java +++ b/router/java/src/net/i2p/router/JobQueueRunner.java @@ -12,6 +12,7 @@ class JobQueueRunner implements Runnable { private Job _currentJob; private Job _lastJob; private long _lastBegin; + private long _lastEnd; public JobQueueRunner(RouterContext context, int id) { _context = context; @@ -33,6 +34,7 @@ class JobQueueRunner implements Runnable { public void stopRunning() { _keepRunning = false; } public void startRunning() { _keepRunning = true; } public long getLastBegin() { return _lastBegin; } + public long getLastEnd() { return _lastEnd; } public void run() { long lastActive = _context.clock().now(); long jobNum = 0; @@ -88,6 +90,7 @@ class JobQueueRunner implements Runnable { lastActive = _context.clock().now(); _lastJob = _currentJob; _currentJob = null; + _lastEnd = lastActive; jobNum++; //if ( (jobNum % 10) == 0) diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 57768696d..5e364f549 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -15,9 +15,9 @@ import net.i2p.CoreVersion; * */ public class RouterVersion { - public final static String ID = "$Revision: 1.56 $ $Date: 2004/10/15 12:39:18 $"; + public final static String ID = "$Revision: 1.57 $ $Date: 2004/10/16 13:00:47 $"; public final static String VERSION = "0.4.1.2"; - public final static long BUILD = 6; + public final static long BUILD = 7; public static void main(String args[]) { System.out.println("I2P Router version: " + VERSION); System.out.println("Router ID: " + RouterVersion.ID); diff --git a/router/java/src/net/i2p/router/RouterWatchdog.java b/router/java/src/net/i2p/router/RouterWatchdog.java index 46099735b..d1140d246 100644 --- a/router/java/src/net/i2p/router/RouterWatchdog.java +++ b/router/java/src/net/i2p/router/RouterWatchdog.java @@ -55,6 +55,12 @@ class RouterWatchdog implements Runnable { Job cur = _context.jobQueue().getLastJob(); if (cur != null) _log.error("Most recent job: " + cur); + _log.error("Last job began: " + + DataHelper.formatDuration(_context.clock().now()-_context.jobQueue().getLastJobBegin()) + + " ago"); + _log.error("Last job ended: " + + DataHelper.formatDuration(_context.clock().now()-_context.jobQueue().getLastJobEnd()) + + " ago"); _log.error("Ready and waiting jobs: " + _context.jobQueue().getReadyCount()); _log.error("Job lag: " + _context.jobQueue().getMaxLag()); _log.error("Participating tunnel count: " + _context.tunnelManager().getParticipatingCount()); diff --git a/router/java/src/net/i2p/router/TunnelInfo.java b/router/java/src/net/i2p/router/TunnelInfo.java index 0f038e5d2..9a303f183 100644 --- a/router/java/src/net/i2p/router/TunnelInfo.java +++ b/router/java/src/net/i2p/router/TunnelInfo.java @@ -328,12 +328,12 @@ public class TunnelInfo extends DataStructureImpl { int i = 0; while (cur != null) { buf.append("\n*Hop ").append(i).append(": ").append(cur.getThisHop()); - if (cur.getEncryptionKey() != null) - buf.append("\n Encryption key: ").append(cur.getEncryptionKey()); - if (cur.getSigningKey() != null) - buf.append("\n Signing key: ").append(cur.getSigningKey()); - if (cur.getVerificationKey() != null) - buf.append("\n Verification key: ").append(cur.getVerificationKey()); + //if (cur.getEncryptionKey() != null) + // buf.append("\n Encryption key: ").append(cur.getEncryptionKey()); + //if (cur.getSigningKey() != null) + // buf.append("\n Signing key: ").append(cur.getSigningKey()); + //if (cur.getVerificationKey() != null) + // buf.append("\n Verification key: ").append(cur.getVerificationKey()); if (cur.getDestination() != null) buf.append("\n Destination: ").append(cur.getDestination().calculateHash().toBase64()); if (cur.getNextHop() != null) @@ -344,7 +344,7 @@ public class TunnelInfo extends DataStructureImpl { buf.append("\n Expiration: ").append("none"); else buf.append("\n Expiration: ").append(new Date(cur.getSettings().getExpiration())); - buf.append("\n Ready: ").append(getIsReady()); + //buf.append("\n Ready: ").append(getIsReady()); cur = cur.getNextHopInfo(); i++; } diff --git a/router/java/src/net/i2p/router/peermanager/CapacityCalculator.java b/router/java/src/net/i2p/router/peermanager/CapacityCalculator.java index d5e5550a4..af2a9dfd0 100644 --- a/router/java/src/net/i2p/router/peermanager/CapacityCalculator.java +++ b/router/java/src/net/i2p/router/peermanager/CapacityCalculator.java @@ -87,8 +87,12 @@ public class CapacityCalculator extends Calculator { long failed = 0; if (curFailed != null) failed = curFailed.getCurrentEventCount() + curFailed.getLastEventCount(); - if (failed > 0) - val -= failed * stretch; + if (failed > 0) { + if ( (period == 10*60*1000) && (curFailed.getCurrentEventCount() > 0) ) + return 0.0d; // their tunnels have failed in the last 0-10 minutes + else + val -= failed * stretch; + } if ( (period == 10*60*1000) && (curRejected.getCurrentEventCount() + curRejected.getLastEventCount() > 0) ) return 0.0d;